diff --git a/.github/workflows/formal.yml b/.github/workflows/formal.yml index 8083c5832c..081129d6f0 100644 --- a/.github/workflows/formal.yml +++ b/.github/workflows/formal.yml @@ -9,65 +9,4 @@ permissions: jobs: build: name: Test Formalities - runs-on: ubuntu-latest - strategy: - fail-fast: false - - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - - name: Determine branch name - run: | - BRANCH="${GITHUB_BASE_REF#refs/heads/}" - echo "Building for $BRANCH" - echo "BRANCH=$BRANCH" >> $GITHUB_ENV - - - name: Test formalities - run: | - source .github/workflows/scripts/ci_helpers.sh - - RET=0 - for commit in $(git rev-list HEAD ^origin/$BRANCH); do - info "=== Checking commit '$commit'" - if git show --format='%P' -s $commit | grep -qF ' '; then - err "Pull request should not include merge commits" - RET=1 - fi - - author="$(git show -s --format=%aN $commit)" - if echo $author | grep -q '\S\+\s\+\S\+'; then - success "Author name ($author) seems ok" - else - err "Author name ($author) need to be your real name 'firstname lastname'" - RET=1 - fi - - subject="$(git show -s --format=%s $commit)" - if echo "$subject" | grep -q -e '^[0-9A-Za-z,+/_\.-]\+: ' -e '^Revert '; then - success "Commit subject line seems ok ($subject)" - else - err "Commit subject line MUST start with ': ' ($subject)" - RET=1 - fi - - body="$(git show -s --format=%b $commit)" - sob="$(git show -s --format='Signed-off-by: %aN <%aE>' $commit)" - if echo "$body" | grep -qF "$sob"; then - success "Signed-off-by match author" - else - err "Signed-off-by is missing or doesn't match author (should be '$sob')" - RET=1 - fi - - if echo "$body" | grep -v "Signed-off-by:"; then - success "A commit message exists" - else - err "Missing commit message. Please describe your changes" - RET=1 - fi - done - - exit $RET + uses: openwrt/actions-shared-workflows/.github/workflows/formal.yml@main diff --git a/config/Config-build.in b/config/Config-build.in index ebfce8add4..24c2bcf130 100644 --- a/config/Config-build.in +++ b/config/Config-build.in @@ -293,6 +293,8 @@ menu "Global build settings" bool "Regular" config PKG_CC_STACKPROTECTOR_STRONG bool "Strong" + config PKG_CC_STACKPROTECTOR_ALL + bool "All" endchoice choice diff --git a/include/hardening.mk b/include/hardening.mk index 6acd862f5c..4a8874261b 100644 --- a/include/hardening.mk +++ b/include/hardening.mk @@ -36,6 +36,11 @@ ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG TARGET_CFLAGS += -fstack-protector-strong endif endif +ifdef CONFIG_PKG_CC_STACKPROTECTOR_ALL + ifeq ($(strip $(PKG_SSP)),1) + TARGET_CFLAGS += -fstack-protector-all + endif +endif ifdef CONFIG_PKG_FORTIFY_SOURCE_1 ifeq ($(strip $(PKG_FORTIFY_SOURCE)),1) TARGET_CFLAGS += -D_FORTIFY_SOURCE=1 diff --git a/include/image.mk b/include/image.mk index 096ccb5f18..f5ab1d7953 100644 --- a/include/image.mk +++ b/include/image.mk @@ -151,17 +151,13 @@ endif # Disable noisy checks by default as in upstream DTC_WARN_FLAGS := \ + -Wno-interrupt_provider \ + -Wno-unique_unit_address \ -Wno-unit_address_vs_reg \ - -Wno-simple_bus_reg \ - -Wno-unit_address_format \ - -Wno-pci_bridge \ - -Wno-pci_device_bus_num \ - -Wno-pci_device_reg \ -Wno-avoid_unnecessary_addr_size \ -Wno-alias_paths \ -Wno-graph_child_address \ - -Wno-graph_port \ - -Wno-unique_unit_address + -Wno-simple_bus_reg DTC_FLAGS += $(DTC_WARN_FLAGS) DTCO_FLAGS += $(DTC_WARN_FLAGS) diff --git a/include/kernel-5.15 b/include/kernel-5.15 index 2948d10bdc..5cc07434b2 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .145 -LINUX_KERNEL_HASH-5.15.145 = b2a49d87605f3a9491581150315e22337c1afb599efc1e2737481be3a2d6d620 +LINUX_VERSION-5.15 = .147 +LINUX_KERNEL_HASH-5.15.147 = 56c1e65625d201db431efda7a3816e7b424071e7cb0245b2ba594d15b1fdfcd4 diff --git a/include/kernel-6.1 b/include/kernel-6.1 index b42886811e..87c6bf5097 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .69 -LINUX_KERNEL_HASH-6.1.69 = 7e3d2694d18ce502068cc88a430da809abbd17d0773268524ebece442612b541 +LINUX_VERSION-6.1 = .74 +LINUX_KERNEL_HASH-6.1.74 = b7fbd1d79faed2ce3570ef79dc1223e4e19c868b86326b14a435db56ebbb2022 diff --git a/include/kernel-build.mk b/include/kernel-build.mk index 5b332258f8..b9513ec414 100644 --- a/include/kernel-build.mk +++ b/include/kernel-build.mk @@ -63,7 +63,7 @@ ifdef CONFIG_COLLECT_KERNEL_DEBUG mkdir -p $(KERNEL_BUILD_DIR)/debug/modules $(CP) $(LINUX_DIR)/vmlinux $(KERNEL_BUILD_DIR)/debug/ -$(CP) \ - $(STAGING_DIR_ROOT)/lib/modules/$(LINUX_VERSION)/* \ + $(STAGING_DIR_ROOT)/lib/modules/$(LINUX_VERSION)/*.ko \ $(KERNEL_BUILD_DIR)/debug/modules/ $(FIND) $(KERNEL_BUILD_DIR)/debug -type f | $(XARGS) $(KERNEL_CROSS)strip --only-keep-debug $(TAR) c -C $(KERNEL_BUILD_DIR) debug \ diff --git a/include/package-defaults.mk b/include/package-defaults.mk index 2cff26b531..30b112c7d8 100644 --- a/include/package-defaults.mk +++ b/include/package-defaults.mk @@ -49,7 +49,7 @@ define Package/Default KCONFIG:= BUILDONLY:= HIDDEN:= - URL:= + URL:=$(PKG_URL) VARIANT:= DEFAULT_VARIANT:= USERID:= diff --git a/include/package-dumpinfo.mk b/include/package-dumpinfo.mk index 6baf10225d..fc25099ad3 100644 --- a/include/package-dumpinfo.mk +++ b/include/package-dumpinfo.mk @@ -37,14 +37,14 @@ $(if $(USERID),Require-User: $(USERID) $(if $(LICENSE),License: $(LICENSE) )$(if $(LICENSE_FILES),LicenseFiles: $(LICENSE_FILES) )$(if $(PKG_CPE_ID),CPE-ID: $(PKG_CPE_ID) +)$(if $(URL),URL: $(URL) )$(if $(ABI_VERSION),ABI-Version: $(ABI_VERSION) )Type: $(if $(Package/$(1)/targets),$(Package/$(1)/targets),$(if $(PKG_TARGETS),$(PKG_TARGETS),ipkg)) $(if $(KCONFIG),Kernel-Config: $(KCONFIG) )$(if $(BUILDONLY),Build-Only: $(BUILDONLY) )$(if $(HIDDEN),Hidden: $(HIDDEN) )Description: $(if $(Package/$(1)/description),$(Package/$(1)/description),$(TITLE)) -$(if $(URL),$(URL) -)$(MAINTAINER) +$(MAINTAINER) @@ $(if $(Package/$(1)/config),Config: $(Package/$(1)/config) diff --git a/include/package-ipkg.mk b/include/package-ipkg.mk index afa2b81eb9..5f5f7e1317 100644 --- a/include/package-ipkg.mk +++ b/include/package-ipkg.mk @@ -185,6 +185,7 @@ $$(call addfield,Depends,$$(Package/$(1)/DEPENDS) )$$(call addfield,Section,$(SECTION) )$$(call addfield,Require-User,$(USERID) )$$(call addfield,SourceDateEpoch,$(PKG_SOURCE_DATE_EPOCH) +)$$(call addfield,URL,$(URL) )$$(if $$(ABIV_$(1)),ABIVersion: $$(ABIV_$(1)) )$(if $(PKG_CPE_ID),CPE-ID: $(PKG_CPE_ID) )$(if $(filter hold,$(PKG_FLAGS)),Status: unknown hold not-installed diff --git a/include/toplevel.mk b/include/toplevel.mk index 328214be1b..f2dfde60cf 100644 --- a/include/toplevel.mk +++ b/include/toplevel.mk @@ -212,7 +212,7 @@ prereq:: prepare-tmpinfo .config check: .config FORCE @+$(NO_TRACE_MAKE) -r -s $@ QUIET= V=s -val.%: FORCE +val.% var.%: FORCE @+$(NO_TRACE_MAKE) -r -s $@ QUIET= V=s WARN_PARALLEL_ERROR = $(if $(BUILD_LOG),,$(and $(filter -j,$(MAKEFLAGS)),$(findstring s,$(OPENWRT_VERBOSE)))) diff --git a/include/verbose.mk b/include/verbose.mk index 4487a207e8..f6aa0d7012 100644 --- a/include/verbose.mk +++ b/include/verbose.mk @@ -30,12 +30,18 @@ ifeq ($(IS_TTY),1) endif define ERROR_MESSAGE - printf "$(_R)%s$(_N)\n" "$(1)" >&8 + { \ + printf "$(_R)%s$(_N)\n" "$(1)" >&9 || \ + printf "$(_R)%s$(_N)\n" "$(1)"; \ + } >&2 2>/dev/null endef ifeq ($(findstring s,$(OPENWRT_VERBOSE)),) define MESSAGE - printf "$(_Y)%s$(_N)\n" "$(1)" >&8 + { \ + printf "$(_Y)%s$(_N)\n" "$(1)" >&8 || \ + printf "$(_Y)%s$(_N)\n" "$(1)"; \ + } 2>/dev/null endef ifeq ($(QUIET),1) @@ -44,9 +50,12 @@ ifeq ($(findstring s,$(OPENWRT_VERBOSE)),) else _DIR:= endif - _NULL:=$(if $(MAKECMDGOALS),$(shell \ + _MESSAGE:=$(if $(MAKECMDGOALS),$(shell \ $(call MESSAGE, make[$(MAKELEVEL)]$(if $(_DIR), -C $(_DIR)) $(MAKECMDGOALS)); \ )) + ifneq ($(strip $(_MESSAGE)),) + $(info $(_MESSAGE)) + endif SUBMAKE=$(MAKE) else SILENT:=>/dev/null $(if $(findstring w,$(OPENWRT_VERBOSE)),,2>&1) diff --git a/package/base-files/files/lib/functions.sh b/package/base-files/files/lib/functions.sh index 851d2f1791..d23a56e0cf 100644 --- a/package/base-files/files/lib/functions.sh +++ b/package/base-files/files/lib/functions.sh @@ -45,7 +45,7 @@ prepend() { local value="$2" local sep="${3:- }" - eval "export ${NO_EXPORT:+-n} -- \"$var=\${$value:+\${$value}\$sep}\$var\"" + eval "export ${NO_EXPORT:+-n} -- \"$var=\$value\${$var:+\${sep}\${$var}}\"" } list_contains() { diff --git a/package/base-files/files/lib/preinit/80_mount_root b/package/base-files/files/lib/preinit/80_mount_root index c3816c2cbf..fa6abcde57 100644 --- a/package/base-files/files/lib/preinit/80_mount_root +++ b/package/base-files/files/lib/preinit/80_mount_root @@ -14,8 +14,27 @@ missing_lines() { IFS="$oIFS" } +# Rootfs mount options can be passed by declaring in the kernel +# cmdline as much options as needed prefixed with "rootfs_mount_options." +# +# Example: +# rootfs_mount_options.compress_algorithm=zstd rootfs_mount_options.noinline_data +# +compose_rootfs_mount_options() { + local mount_options + local cmdlinevar + + for cmdlinevar in $(cat /proc/cmdline); do + if [ "$cmdlinevar" != "${cmdlinevar#rootfs_mount_options\.}" ]; then + append mount_options "${cmdlinevar#rootfs_mount_options\.}" + fi + done + + echo $mount_options +} + do_mount_root() { - mount_root + mount_root start "$(compose_rootfs_mount_options)" boot_run_hook preinit_mount_root [ -f /sysupgrade.tgz -o -f /tmp/sysupgrade.tar ] && { echo "- config restore -" diff --git a/package/boot/arm-trusted-firmware-rockchip/Makefile b/package/boot/arm-trusted-firmware-rockchip/Makefile index aaae4ce392..6fbcbef0a8 100644 --- a/package/boot/arm-trusted-firmware-rockchip/Makefile +++ b/package/boot/arm-trusted-firmware-rockchip/Makefile @@ -7,10 +7,10 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=2.9 +PKG_VERSION:=2.10 PKG_RELEASE:=1 -PKG_HASH:=76a66a1de0c01aeb83dfc7b72b51173fe62c6e51d6fca17cc562393117bed08b +PKG_HASH:=88215a62291b9ba87da8e50b077741103cdc08fb6c9e1ebd34dfaace746d3201 PKG_MAINTAINER:=Tobias Maedel diff --git a/package/boot/uboot-bcm53xx/Makefile b/package/boot/uboot-bcm53xx/Makefile index ab80b9608a..f1c026e25b 100644 --- a/package/boot/uboot-bcm53xx/Makefile +++ b/package/boot/uboot-bcm53xx/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=2023.04 -PKG_HASH:=e31cac91545ff41b71cec5d8c22afd695645cd6e2a442ccdacacd60534069341 +PKG_VERSION:=2024.01 +PKG_HASH:=b99611f1ed237bf3541bdc8434b68c96a6e05967061f992443cb30aabebef5b3 PKG_RELEASE:=$(AUTORELEASE) include $(INCLUDE_DIR)/u-boot.mk diff --git a/package/boot/uboot-bcm53xx/patches/0001-nand-brcmnand-add-iproc-support.patch b/package/boot/uboot-bcm53xx/patches/0001-nand-brcmnand-add-iproc-support.patch deleted file mode 100644 index fe6f4d944a..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0001-nand-brcmnand-add-iproc-support.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 854dc4b790ce1291326d52b8405ebe771bff2edd Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Wed, 8 Mar 2023 22:42:31 +0100 -Subject: [PATCH 1/5] nand: brcmnand: add iproc support - -Add support for the iproc Broadcom NAND controller, -used in Northstar SoCs for example. Based on the Linux -driver. - -Cc: Philippe Reynes -Cc: Dario Binacchi -Reviewed-by: Michael Trimarchi -Signed-off-by: Linus Walleij -Acked-by: William Zhang -Link: https://lore.kernel.org/all/20230308214231.378013-1-linus.walleij@linaro.org/ -Signed-off-by: Dario Binacchi ---- - drivers/mtd/nand/raw/Kconfig | 7 + - drivers/mtd/nand/raw/brcmnand/Makefile | 1 + - drivers/mtd/nand/raw/brcmnand/iproc_nand.c | 148 +++++++++++++++++++++ - 3 files changed, 156 insertions(+) - create mode 100644 drivers/mtd/nand/raw/brcmnand/iproc_nand.c - ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -156,6 +156,13 @@ config NAND_BRCMNAND_63158 - help - Enable support for broadcom nand driver on bcm63158. - -+config NAND_BRCMNAND_IPROC -+ bool "Support Broadcom NAND controller on the iproc family" -+ depends on NAND_BRCMNAND -+ help -+ Enable support for broadcom nand driver on the Broadcom -+ iproc family such as Northstar (BCM5301x, BCM4708...) -+ - config NAND_DAVINCI - bool "Support TI Davinci NAND controller" - select SYS_NAND_SELF_INIT if TARGET_DA850EVM ---- a/drivers/mtd/nand/raw/brcmnand/Makefile -+++ b/drivers/mtd/nand/raw/brcmnand/Makefile -@@ -6,5 +6,6 @@ obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6 - obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o - obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o - obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o -+obj-$(CONFIG_NAND_BRCMNAND_IPROC) += iproc_nand.o - obj-$(CONFIG_NAND_BRCMNAND) += brcmnand.o - obj-$(CONFIG_NAND_BRCMNAND) += brcmnand_compat.o ---- /dev/null -+++ b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c -@@ -0,0 +1,148 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Code borrowed from the Linux driver -+ * Copyright (C) 2015 Broadcom Corporation -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "brcmnand.h" -+ -+struct iproc_nand_soc { -+ struct brcmnand_soc soc; -+ void __iomem *idm_base; -+ void __iomem *ext_base; -+}; -+ -+#define IPROC_NAND_CTLR_READY_OFFSET 0x10 -+#define IPROC_NAND_CTLR_READY BIT(0) -+ -+#define IPROC_NAND_IO_CTRL_OFFSET 0x00 -+#define IPROC_NAND_APB_LE_MODE BIT(24) -+#define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6) -+ -+static bool iproc_nand_intc_ack(struct brcmnand_soc *soc) -+{ -+ struct iproc_nand_soc *priv = -+ container_of(soc, struct iproc_nand_soc, soc); -+ void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET; -+ u32 val = brcmnand_readl(mmio); -+ -+ if (val & IPROC_NAND_CTLR_READY) { -+ brcmnand_writel(IPROC_NAND_CTLR_READY, mmio); -+ return true; -+ } -+ -+ return false; -+} -+ -+static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en) -+{ -+ struct iproc_nand_soc *priv = -+ container_of(soc, struct iproc_nand_soc, soc); -+ void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; -+ u32 val = brcmnand_readl(mmio); -+ -+ if (en) -+ val |= IPROC_NAND_INT_CTRL_READ_ENABLE; -+ else -+ val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE; -+ -+ brcmnand_writel(val, mmio); -+} -+ -+static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare, -+ bool is_param) -+{ -+ struct iproc_nand_soc *priv = -+ container_of(soc, struct iproc_nand_soc, soc); -+ void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; -+ u32 val; -+ -+ val = brcmnand_readl(mmio); -+ -+ /* -+ * In the case of BE or when dealing with NAND data, always configure -+ * the APB bus to LE mode before accessing the FIFO and back to BE mode -+ * after the access is done -+ */ -+ if (IS_ENABLED(CONFIG_SYS_BIG_ENDIAN) || !is_param) { -+ if (prepare) -+ val |= IPROC_NAND_APB_LE_MODE; -+ else -+ val &= ~IPROC_NAND_APB_LE_MODE; -+ } else { /* when in LE accessing the parameter page, keep APB in BE */ -+ val &= ~IPROC_NAND_APB_LE_MODE; -+ } -+ -+ brcmnand_writel(val, mmio); -+} -+ -+static int iproc_nand_probe(struct udevice *dev) -+{ -+ struct udevice *pdev = dev; -+ struct iproc_nand_soc *priv = dev_get_priv(dev); -+ struct brcmnand_soc *soc; -+ struct resource res; -+ int ret; -+ -+ soc = &priv->soc; -+ -+ ret = dev_read_resource_byname(pdev, "iproc-idm", &res); -+ if (ret) -+ return ret; -+ -+ priv->idm_base = devm_ioremap(dev, res.start, resource_size(&res)); -+ if (IS_ERR(priv->idm_base)) -+ return PTR_ERR(priv->idm_base); -+ -+ ret = dev_read_resource_byname(pdev, "iproc-ext", &res); -+ if (ret) -+ return ret; -+ -+ priv->ext_base = devm_ioremap(dev, res.start, resource_size(&res)); -+ if (IS_ERR(priv->ext_base)) -+ return PTR_ERR(priv->ext_base); -+ -+ soc->ctlrdy_ack = iproc_nand_intc_ack; -+ soc->ctlrdy_set_enabled = iproc_nand_intc_set; -+ soc->prepare_data_bus = iproc_nand_apb_access; -+ -+ return brcmnand_probe(pdev, soc); -+} -+ -+static const struct udevice_id iproc_nand_dt_ids[] = { -+ { -+ .compatible = "brcm,nand-iproc", -+ }, -+ { /* sentinel */ } -+}; -+ -+U_BOOT_DRIVER(iproc_nand) = { -+ .name = "iproc-nand", -+ .id = UCLASS_MTD, -+ .of_match = iproc_nand_dt_ids, -+ .probe = iproc_nand_probe, -+ .priv_auto = sizeof(struct iproc_nand_soc), -+}; -+ -+void board_nand_init(void) -+{ -+ struct udevice *dev; -+ int ret; -+ -+ ret = uclass_get_device_by_driver(UCLASS_MTD, -+ DM_DRIVER_GET(iproc_nand), &dev); -+ if (ret && ret != -ENODEV) -+ pr_err("Failed to initialize %s. (error %d)\n", dev->name, -+ ret); -+} diff --git a/package/boot/uboot-bcm53xx/patches/0002-mtd-rawnand-nand_base-Handle-algorithm-selection.patch b/package/boot/uboot-bcm53xx/patches/0002-mtd-rawnand-nand_base-Handle-algorithm-selection.patch deleted file mode 100644 index eb2a5ec703..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0002-mtd-rawnand-nand_base-Handle-algorithm-selection.patch +++ /dev/null @@ -1,80 +0,0 @@ -From d75483f8892f3a0dfb8f5aa4147e72c02c8b034c Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Fri, 7 Apr 2023 15:40:05 +0200 -Subject: [PATCH 2/5] mtd: rawnand: nand_base: Handle algorithm selection - -For BRCMNAND with 1-bit BCH ECC (BCH-1) such as used on the -D-Link DIR-885L and DIR-890L routers, we need to explicitly -select the ECC like this in the device tree: - - nand-ecc-algo = "bch"; - nand-ecc-strength = <1>; - nand-ecc-step-size = <512>; - -This is handled by the Linux kernel but U-Boot core does -not respect this. Fix it up by parsing the algorithm and -preserve the behaviour using this property to select -software BCH as far as possible. - -Reviewed-by: Michael Trimarchi -Acked-by: William Zhang -Signed-off-by: Linus Walleij -Tested-by: Tom Rini [am335x_evm] -Link: https://lore.kernel.org/all/20230407134008.1939717-3-linus.walleij@linaro.org/ -Signed-off-by: Dario Binacchi ---- - drivers/mtd/nand/raw/nand_base.c | 29 +++++++++++++++++++++++++---- - 1 file changed, 25 insertions(+), 4 deletions(-) - ---- a/drivers/mtd/nand/raw/nand_base.c -+++ b/drivers/mtd/nand/raw/nand_base.c -@@ -4487,6 +4487,7 @@ EXPORT_SYMBOL(nand_detect); - static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, ofnode node) - { - int ret, ecc_mode = -1, ecc_strength, ecc_step; -+ int ecc_algo = NAND_ECC_UNKNOWN; - const char *str; - - ret = ofnode_read_s32_default(node, "nand-bus-width", -1); -@@ -4512,10 +4513,22 @@ static int nand_dt_init(struct mtd_info - ecc_mode = NAND_ECC_SOFT_BCH; - } - -- if (ecc_mode == NAND_ECC_SOFT) { -- str = ofnode_read_string(node, "nand-ecc-algo"); -- if (str && !strcmp(str, "bch")) -- ecc_mode = NAND_ECC_SOFT_BCH; -+ str = ofnode_read_string(node, "nand-ecc-algo"); -+ if (str) { -+ /* -+ * If we are in NAND_ECC_SOFT mode, just alter the -+ * soft mode to BCH here. No change of algorithm. -+ */ -+ if (ecc_mode == NAND_ECC_SOFT) { -+ if (!strcmp(str, "bch")) -+ ecc_mode = NAND_ECC_SOFT_BCH; -+ } else { -+ if (!strcmp(str, "bch")) { -+ ecc_algo = NAND_ECC_BCH; -+ } else if (!strcmp(str, "hamming")) { -+ ecc_algo = NAND_ECC_HAMMING; -+ } -+ } - } - - ecc_strength = ofnode_read_s32_default(node, -@@ -4529,6 +4542,14 @@ static int nand_dt_init(struct mtd_info - return -EINVAL; - } - -+ /* -+ * Chip drivers may have assigned default algorithms here, -+ * onlt override it if we have found something explicitly -+ * specified in the device tree. -+ */ -+ if (ecc_algo != NAND_ECC_UNKNOWN) -+ chip->ecc.algo = ecc_algo; -+ - if (ecc_mode >= 0) - chip->ecc.mode = ecc_mode; - diff --git a/package/boot/uboot-bcm53xx/patches/0003-arm-dts-Import-device-tree-for-Broadcom-Northstar.patch b/package/boot/uboot-bcm53xx/patches/0003-arm-dts-Import-device-tree-for-Broadcom-Northstar.patch deleted file mode 100644 index 6a4eef77f8..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0003-arm-dts-Import-device-tree-for-Broadcom-Northstar.patch +++ /dev/null @@ -1,659 +0,0 @@ -From 3d6098a662b7ff5b80c4b75c54fcd1b2baf9f150 Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Mon, 24 Apr 2023 09:38:28 +0200 -Subject: [PATCH 3/5] arm: dts: Import device tree for Broadcom Northstar -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This brings in the main SoC device tree used by the -Broadcom Northstar chipset, i.e. BCM4709x and BCM5301x. -This is taken from the v6.3 Linux kernel. - -Cc: Rafał Miłecki -Signed-off-by: Linus Walleij ---- - arch/arm/dts/bcm5301x.dtsi | 581 ++++++++++++++++++++++++++++ - include/dt-bindings/clock/bcm-nsp.h | 51 +++ - 2 files changed, 632 insertions(+) - create mode 100644 arch/arm/dts/bcm5301x.dtsi - create mode 100644 include/dt-bindings/clock/bcm-nsp.h - ---- /dev/null -+++ b/arch/arm/dts/bcm5301x.dtsi -@@ -0,0 +1,581 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * Generic DTS part for all BCM53010, BCM53011, BCM53012, BCM53014, BCM53015, -+ * BCM53016, BCM53017, BCM53018, BCM4707, BCM4708 and BCM4709 SoCs -+ * -+ * Copyright 2013-2014 Hauke Mehrtens -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ interrupt-parent = <&gic>; -+ -+ chipcommon-a-bus@18000000 { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x18000000 0x00001000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@300 { -+ compatible = "ns16550"; -+ reg = <0x0300 0x100>; -+ interrupts = ; -+ clocks = <&iprocslow>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@400 { -+ compatible = "ns16550"; -+ reg = <0x0400 0x100>; -+ interrupts = ; -+ clocks = <&iprocslow>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinmux_uart1>; -+ status = "disabled"; -+ }; -+ }; -+ -+ mpcore-bus@19000000 { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@0 { -+ #clock-cells = <0>; -+ compatible = "brcm,nsp-armpll"; -+ clocks = <&osc>; -+ reg = <0x00000 0x1000>; -+ }; -+ -+ scu@20000 { -+ compatible = "arm,cortex-a9-scu"; -+ reg = <0x20000 0x100>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x20>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ watchdog@20620 { -+ compatible = "arm,cortex-a9-twd-wdt"; -+ reg = <0x20620 0x20>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, -+ <0x20100 0x100>; -+ }; -+ -+ L2: cache-controller@22000 { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ arm,shared-override; -+ prefetch-data = <1>; -+ prefetch-instr = <1>; -+ cache-level = <2>; -+ }; -+ }; -+ -+ pmu { -+ compatible = "arm,cortex-a9-pmu"; -+ interrupts = -+ , -+ ; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ iprocmed: iprocmed { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iprocslow: iprocslow { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi@18000000 { -+ compatible = "brcm,bus-axi"; -+ reg = <0x18000000 0x1000>; -+ ranges = <0x00000000 0x18000000 0x00100000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0x000fffff 0xffff>; -+ interrupt-map = -+ /* ChipCommon */ -+ <0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Switch Register Access Block */ -+ <0x00007000 0 &gic GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 1 &gic GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 2 &gic GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 3 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 4 &gic GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 5 &gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 6 &gic GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 7 &gic GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 8 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 9 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 10 &gic GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 11 &gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 12 &gic GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 0 */ -+ <0x00012000 0 &gic GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 2 &gic GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 3 &gic GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 4 &gic GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 5 &gic GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 1 */ -+ <0x00013000 0 &gic GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 1 &gic GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 2 &gic GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 3 &gic GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 4 &gic GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 5 &gic GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 2 */ -+ <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 5 &gic GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* USB 2.0 Controller */ -+ <0x00021000 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* USB 3.0 Controller */ -+ <0x00023000 0 &gic GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 0 */ -+ <0x00024000 0 &gic GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 1 */ -+ <0x00025000 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 2 */ -+ <0x00026000 0 &gic GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 3 */ -+ <0x00027000 0 &gic GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* NAND Controller */ -+ <0x00028000 0 &gic GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 1 &gic GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 2 &gic GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 3 &gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 4 &gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 5 &gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 6 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 7 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; -+ -+ chipcommon: chipcommon@0 { -+ reg = <0x00000000 0x1000>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ pcie0: pcie@12000 { -+ reg = <0x00012000 0x1000>; -+ }; -+ -+ pcie1: pcie@13000 { -+ reg = <0x00013000 0x1000>; -+ }; -+ -+ pcie2: pcie@14000 { -+ reg = <0x00014000 0x1000>; -+ }; -+ -+ usb2: usb2@21000 { -+ reg = <0x00021000 0x1000>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ interrupt-parent = <&gic>; -+ -+ ehci: usb@21000 { -+ #usb-cells = <0>; -+ -+ compatible = "generic-ehci"; -+ reg = <0x00021000 0x1000>; -+ interrupts = ; -+ phys = <&usb2_phy>; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ehci_port1: port@1 { -+ reg = <1>; -+ #trigger-source-cells = <0>; -+ }; -+ -+ ehci_port2: port@2 { -+ reg = <2>; -+ #trigger-source-cells = <0>; -+ }; -+ }; -+ -+ ohci: usb@22000 { -+ #usb-cells = <0>; -+ -+ compatible = "generic-ohci"; -+ reg = <0x00022000 0x1000>; -+ interrupts = ; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ohci_port1: port@1 { -+ reg = <1>; -+ #trigger-source-cells = <0>; -+ }; -+ -+ ohci_port2: port@2 { -+ reg = <2>; -+ #trigger-source-cells = <0>; -+ }; -+ }; -+ }; -+ -+ usb3: usb3@23000 { -+ reg = <0x00023000 0x1000>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ interrupt-parent = <&gic>; -+ -+ xhci: usb@23000 { -+ #usb-cells = <0>; -+ -+ compatible = "generic-xhci"; -+ reg = <0x00023000 0x1000>; -+ interrupts = ; -+ phys = <&usb3_phy>; -+ phy-names = "usb"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ xhci_port1: port@1 { -+ reg = <1>; -+ #trigger-source-cells = <0>; -+ }; -+ }; -+ }; -+ -+ gmac0: ethernet@24000 { -+ reg = <0x24000 0x800>; -+ }; -+ -+ gmac1: ethernet@25000 { -+ reg = <0x25000 0x800>; -+ }; -+ -+ gmac2: ethernet@26000 { -+ reg = <0x26000 0x800>; -+ }; -+ -+ gmac3: ethernet@27000 { -+ reg = <0x27000 0x800>; -+ }; -+ }; -+ -+ pwm: pwm@18002000 { -+ compatible = "brcm,iproc-pwm"; -+ reg = <0x18002000 0x28>; -+ clocks = <&osc>; -+ #pwm-cells = <3>; -+ status = "disabled"; -+ }; -+ -+ mdio: mdio@18003000 { -+ compatible = "brcm,iproc-mdio"; -+ reg = <0x18003000 0x8>; -+ #size-cells = <0>; -+ #address-cells = <1>; -+ }; -+ -+ mdio-mux@18003000 { -+ compatible = "mdio-mux-mmioreg", "mdio-mux"; -+ mdio-parent-bus = <&mdio>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x18003000 0x4>; -+ mux-mask = <0x200>; -+ -+ mdio@0 { -+ reg = <0x0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ usb3_phy: usb3-phy@10 { -+ compatible = "brcm,ns-ax-usb3-phy"; -+ reg = <0x10>; -+ usb3-dmp-syscon = <&usb3_dmp>; -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ usb3_dmp: syscon@18105000 { -+ reg = <0x18105000 0x1000>; -+ }; -+ -+ uart2: serial@18008000 { -+ compatible = "ns16550a"; -+ reg = <0x18008000 0x20>; -+ clocks = <&iprocslow>; -+ interrupts = ; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18009000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18009000 0x50>; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ dmu-bus@1800c000 { -+ compatible = "simple-bus"; -+ ranges = <0 0x1800c000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ cru-bus@100 { -+ compatible = "brcm,ns-cru", "simple-mfd"; -+ reg = <0x100 0x1a4>; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ lcpll0: clock-controller@100 { -+ #clock-cells = <1>; -+ compatible = "brcm,nsp-lcpll0"; -+ reg = <0x100 0x14>; -+ clocks = <&osc>; -+ clock-output-names = "lcpll0", "pcie_phy", -+ "sdio", "ddr_phy"; -+ }; -+ -+ genpll: clock-controller@140 { -+ #clock-cells = <1>; -+ compatible = "brcm,nsp-genpll"; -+ reg = <0x140 0x24>; -+ clocks = <&osc>; -+ clock-output-names = "genpll", "phy", -+ "ethernetclk", -+ "usbclk", "iprocfast", -+ "sata1", "sata2"; -+ }; -+ -+ usb2_phy: phy@164 { -+ compatible = "brcm,ns-usb2-phy"; -+ reg = <0x164 0x4>; -+ brcm,syscon-clkset = <&cru_clkset>; -+ clocks = <&genpll BCM_NSP_GENPLL_USB_PHY_REF_CLK>; -+ clock-names = "phy-ref-clk"; -+ #phy-cells = <0>; -+ }; -+ -+ cru_clkset: syscon@180 { -+ compatible = "brcm,cru-clkset", "syscon"; -+ reg = <0x180 0x4>; -+ }; -+ -+ pinctrl: pinctrl@1c0 { -+ compatible = "brcm,bcm4708-pinmux"; -+ reg = <0x1c0 0x24>; -+ reg-names = "cru_gpio_control"; -+ -+ spi-pins { -+ groups = "spi_grp"; -+ function = "spi"; -+ }; -+ -+ pinmux_i2c: i2c-pins { -+ groups = "i2c_grp"; -+ function = "i2c"; -+ }; -+ -+ pinmux_pwm: pwm-pins { -+ groups = "pwm0_grp", "pwm1_grp", -+ "pwm2_grp", "pwm3_grp"; -+ function = "pwm"; -+ }; -+ -+ pinmux_uart1: uart1-pins { -+ groups = "uart1_grp"; -+ function = "uart1"; -+ }; -+ }; -+ -+ thermal: thermal@2c0 { -+ compatible = "brcm,ns-thermal"; -+ reg = <0x2c0 0x10>; -+ #thermal-sensor-cells = <0>; -+ }; -+ }; -+ }; -+ -+ srab: ethernet-switch@18007000 { -+ compatible = "brcm,bcm53011-srab", "brcm,bcm5301x-srab"; -+ reg = <0x18007000 0x1000>; -+ -+ status = "disabled"; -+ -+ /* ports are defined in board DTS */ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ }; -+ -+ rng: rng@18004000 { -+ compatible = "brcm,bcm5301x-rng"; -+ reg = <0x18004000 0x14>; -+ }; -+ -+ nand_controller: nand-controller@18028000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", "brcm,brcmnand"; -+ reg = <0x18028000 0x600>, <0x1811a408 0x600>, <0x18028f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ brcm,nand-has-wp; -+ }; -+ -+ spi@18029200 { -+ compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi"; -+ reg = <0x18029200 0x184>, -+ <0x18029000 0x124>, -+ <0x1811b408 0x004>, -+ <0x180293a0 0x01c>; -+ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "mspi_done", -+ "mspi_halted", -+ "spi_lr_fullness_reached", -+ "spi_lr_session_aborted", -+ "spi_lr_impatient", -+ "spi_lr_session_done", -+ "spi_lr_overread"; -+ clocks = <&iprocmed>; -+ clock-names = "iprocmed"; -+ num-cs = <2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ spi_nor: flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-max-frequency = <20000000>; -+ status = "disabled"; -+ -+ partitions { -+ compatible = "brcm,bcm947xx-cfe-partitions"; -+ }; -+ }; -+ }; -+ -+ thermal-zones { -+ cpu_thermal: cpu-thermal { -+ polling-delay-passive = <0>; -+ polling-delay = <1000>; -+ coefficients = <(-556) 418000>; -+ thermal-sensors = <&thermal>; -+ -+ trips { -+ cpu-crit { -+ temperature = <125000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ -+ cooling-maps { -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/include/dt-bindings/clock/bcm-nsp.h -@@ -0,0 +1,51 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2015 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef _CLOCK_BCM_NSP_H -+#define _CLOCK_BCM_NSP_H -+ -+/* GENPLL clock channel ID */ -+#define BCM_NSP_GENPLL 0 -+#define BCM_NSP_GENPLL_PHY_CLK 1 -+#define BCM_NSP_GENPLL_ENET_SW_CLK 2 -+#define BCM_NSP_GENPLL_USB_PHY_REF_CLK 3 -+#define BCM_NSP_GENPLL_IPROCFAST_CLK 4 -+#define BCM_NSP_GENPLL_SATA1_CLK 5 -+#define BCM_NSP_GENPLL_SATA2_CLK 6 -+ -+/* LCPLL0 clock channel ID */ -+#define BCM_NSP_LCPLL0 0 -+#define BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK 1 -+#define BCM_NSP_LCPLL0_SDIO_CLK 2 -+#define BCM_NSP_LCPLL0_DDR_PHY_CLK 3 -+ -+#endif /* _CLOCK_BCM_NSP_H */ diff --git a/package/boot/uboot-bcm53xx/patches/0004-arm-Add-support-for-the-Broadcom-Northstar-SoCs.patch b/package/boot/uboot-bcm53xx/patches/0004-arm-Add-support-for-the-Broadcom-Northstar-SoCs.patch deleted file mode 100644 index 92eaa46e51..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0004-arm-Add-support-for-the-Broadcom-Northstar-SoCs.patch +++ /dev/null @@ -1,66 +0,0 @@ -From b81ea0a64b01ae42e8b41d2a8b9a3fabffe97489 Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Mon, 24 Apr 2023 09:38:29 +0200 -Subject: [PATCH 4/5] arm: Add support for the Broadcom Northstar SoCs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The original Northstar is an ARM SoC series that comprise -BCM4709x and BCM5301x and uses a dual-core Cortex A9, the -global timer and a few other things. - -This series should not be confused with North Star Plus -(NSP) which is partly supported by U-Boot already. - -The SoC is well supported by the Linux kernel and OpenWrt -as it is used in many routers. - -Since we currently don't need any chip-specific quirks -and can get the system up from just the device tree, a -mach-* directory doesn't even need to be added, just -some small Kconfig fragments. - -Cc: Rafał Miłecki -Signed-off-by: Linus Walleij ---- - arch/arm/Kconfig | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -357,7 +357,7 @@ config SYS_ARM_ARCH - - choice - prompt "Select the ARM data write cache policy" -- default SYS_ARM_CACHE_WRITETHROUGH if TARGET_BCMCYGNUS || RZA1 -+ default SYS_ARM_CACHE_WRITETHROUGH if TARGET_BCMCYGNUS || TARGET_BCMNS || RZA1 - default SYS_ARM_CACHE_WRITEBACK - - config SYS_ARM_CACHE_WRITEBACK -@@ -670,6 +670,25 @@ config TARGET_BCMCYGNUS - imply HASH_VERIFY - imply NETDEVICES - -+config TARGET_BCMNS -+ bool "Support Broadcom Northstar" -+ select CPU_V7A -+ select DM -+ select DM_GPIO -+ select DM_SERIAL -+ select OF_CONTROL -+ select TIMER -+ select SYS_NS16550 -+ select ARM_GLOBAL_TIMER -+ imply SYS_THUMB_BUILD -+ imply MTD_RAW_NAND -+ imply NAND_BRCMNAND -+ imply NAND_BRCMNAND_IPROC -+ help -+ Support for Broadcom Northstar SoCs. NS is a dual-core 32-bit -+ ARMv7 Cortex-A9 SoC family including BCM4708, BCM47094, -+ BCM5301x etc. -+ - config TARGET_BCMNS2 - bool "Support Broadcom Northstar2" - select ARM64 diff --git a/package/boot/uboot-bcm53xx/patches/0005-board-Add-new-Broadcom-Northstar-board.patch b/package/boot/uboot-bcm53xx/patches/0005-board-Add-new-Broadcom-Northstar-board.patch deleted file mode 100644 index 158718133d..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0005-board-Add-new-Broadcom-Northstar-board.patch +++ /dev/null @@ -1,372 +0,0 @@ -From 652a6fa45b6c9d52dd9685fc12ad662e54a9092e Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Mon, 24 Apr 2023 09:38:30 +0200 -Subject: [PATCH 5/5] board: Add new Broadcom Northstar board -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds a simple Northstar "BRCMNS" board to be used with -the BCM4708x and BCM5301x chips. - -The main intention is to use this with the D-Link DIR-890L -and DIR-885L routers for loading the kernel into RAM from -NAND memory using the BCH-1 ECC and using the separately -submitted SEAMA load command, so we are currently not adding -support for things such as networking. - -The DTS file is a multiplatform NorthStar board, designed to -be usable with several NorthStar designs by avoiding any -particulars not related to the operation of U-Boot. - -If other board need other ECC for example, they need to -create a separate DTS file and augment the code, but I don't -know if any other users will turn up. - -Cc: Rafał Miłecki -Signed-off-by: Linus Walleij ---- - arch/arm/Kconfig | 1 + - arch/arm/dts/Makefile | 2 ++ - arch/arm/dts/ns-board.dts | 57 ++++++++++++++++++++++++++++++ - board/broadcom/bcmns/Kconfig | 12 +++++++ - board/broadcom/bcmns/MAINTAINERS | 6 ++++ - board/broadcom/bcmns/Makefile | 2 ++ - board/broadcom/bcmns/ns.c | 60 ++++++++++++++++++++++++++++++++ - configs/bcmns_defconfig | 41 ++++++++++++++++++++++ - doc/board/broadcom/index.rst | 1 + - doc/board/broadcom/northstar.rst | 44 +++++++++++++++++++++++ - include/configs/bcmns.h | 49 ++++++++++++++++++++++++++ - 11 files changed, 275 insertions(+) - create mode 100644 arch/arm/dts/ns-board.dts - create mode 100644 board/broadcom/bcmns/Kconfig - create mode 100644 board/broadcom/bcmns/MAINTAINERS - create mode 100644 board/broadcom/bcmns/Makefile - create mode 100644 board/broadcom/bcmns/ns.c - create mode 100644 configs/bcmns_defconfig - create mode 100644 doc/board/broadcom/northstar.rst - create mode 100644 include/configs/bcmns.h - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -2286,6 +2286,7 @@ source "board/Marvell/octeontx2/Kconfig" - source "board/armltd/vexpress/Kconfig" - source "board/armltd/vexpress64/Kconfig" - source "board/cortina/presidio-asic/Kconfig" -+source "board/broadcom/bcmns/Kconfig" - source "board/broadcom/bcmns3/Kconfig" - source "board/cavium/thunderx/Kconfig" - source "board/eets/pdu001/Kconfig" ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -1185,6 +1185,8 @@ dtb-$(CONFIG_ARCH_BCM283X) += \ - bcm2837-rpi-cm3-io3.dtb \ - bcm2711-rpi-4-b.dtb - -+dtb-$(CONFIG_TARGET_BCMNS) += ns-board.dtb -+ - dtb-$(CONFIG_TARGET_BCMNS3) += ns3-board.dtb - - dtb-$(CONFIG_ARCH_BCMSTB) += bcm7xxx.dtb ---- /dev/null -+++ b/arch/arm/dts/ns-board.dts -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+ -+/dts-v1/; -+ -+#include "bcm5301x.dtsi" -+ -+/ { -+ /* -+ * The Northstar does not have a proper fallback compatible, but -+ * these basic chips will suffice. -+ */ -+ model = "Northstar model"; -+ compatible = "brcm,bcm47094", "brcm,bcm4708"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ interrupt-parent = <&gic>; -+ -+ memory { -+ device_type = "memory"; -+ reg = <0x00000000 0x08000000>, -+ <0x88000000 0x08000000>; -+ }; -+ -+ aliases { -+ serial0 = &uart0; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ nand-controller@18028000 { -+ nandcs: nand@0 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ /* -+ * Same as using the bcm5301x-nand-cs0-bch1.dtsi -+ * include from the Linux kernel. -+ */ -+ nand-ecc-algo = "bch"; -+ nand-ecc-strength = <1>; -+ nand-ecc-step-size = <512>; -+ -+ partitions { -+ compatible = "brcm,bcm947xx-cfe-partitions"; -+ }; -+ }; -+ }; -+}; -+ -+&uart0 { -+ clock-frequency = <125000000>; -+ status = "okay"; -+}; ---- /dev/null -+++ b/board/broadcom/bcmns/Kconfig -@@ -0,0 +1,12 @@ -+if TARGET_BCMNS -+ -+config SYS_BOARD -+ default "bcmns" -+ -+config SYS_VENDOR -+ default "broadcom" -+ -+config SYS_CONFIG_NAME -+ default "bcmns" -+ -+endif ---- /dev/null -+++ b/board/broadcom/bcmns/MAINTAINERS -@@ -0,0 +1,6 @@ -+BCMNS BOARD -+M: Linus Walleij -+S: Maintained -+F: board/broadcom/bcmnsp/ -+F: configs/bcmnsp_defconfig -+F: include/configs/bcmnsp.h ---- /dev/null -+++ b/board/broadcom/bcmns/Makefile -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0-or-later -+obj-y := ns.o ---- /dev/null -+++ b/board/broadcom/bcmns/ns.c -@@ -0,0 +1,60 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Broadcom Northstar generic board set-up code -+ * Copyright (C) 2023 Linus Walleij -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+DECLARE_GLOBAL_DATA_PTR; -+ -+int dram_init(void) -+{ -+ return fdtdec_setup_mem_size_base(); -+} -+ -+int dram_init_banksize(void) -+{ -+ return fdtdec_setup_memory_banksize(); -+} -+ -+int board_late_init(void) -+{ -+ /* LEDs etc can be initialized here */ -+ return 0; -+} -+ -+int board_init(void) -+{ -+ return 0; -+} -+ -+void reset_cpu(void) -+{ -+} -+ -+int print_cpuinfo(void) -+{ -+ printf("BCMNS Northstar SoC\n"); -+ return 0; -+} -+ -+int misc_init_r(void) -+{ -+ return 0; -+} -+ -+int ft_board_setup(void *fdt, struct bd_info *bd) -+{ -+ printf("Northstar board setup: DTB at 0x%08lx\n", (ulong)fdt); -+ return 0; -+} -+ ---- /dev/null -+++ b/configs/bcmns_defconfig -@@ -0,0 +1,41 @@ -+CONFIG_ARM=y -+CONFIG_TARGET_BCMNS=y -+CONFIG_TEXT_BASE=0x00008000 -+CONFIG_SYS_MALLOC_LEN=0x2000000 -+CONFIG_SYS_MALLOC_F_LEN=0x8000 -+CONFIG_NR_DRAM_BANKS=2 -+CONFIG_DEFAULT_DEVICE_TREE="ns-board" -+CONFIG_IDENT_STRING="Broadcom Northstar" -+CONFIG_SYS_LOAD_ADDR=0x00008000 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x00100000 -+# CONFIG_BOOTSTD is not set -+CONFIG_AUTOBOOT_KEYED=y -+CONFIG_AUTOBOOT_PROMPT="Boot Northstar system in %d seconds\n" -+CONFIG_BOOTDELAY=1 -+CONFIG_USE_BOOTCOMMAND=y -+CONFIG_BOOTCOMMAND="run bootcmd_dlink_dir8xxl" -+CONFIG_SYS_PROMPT="northstar> " -+CONFIG_ENV_VARS_UBOOT_CONFIG=y -+CONFIG_OF_BOARD_SETUP=y -+CONFIG_OF_STDOUT_VIA_ALIAS=y -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_HUSH_PARSER=y -+CONFIG_SYS_MAXARGS=64 -+CONFIG_CMD_SEAMA=y -+CONFIG_CMD_BOOTZ=y -+CONFIG_CMD_CACHE=y -+CONFIG_OF_EMBED=y -+CONFIG_USE_HOSTNAME=y -+CONFIG_HOSTNAME="NS" -+CONFIG_CLK=y -+CONFIG_MTD=y -+CONFIG_DM_MTD=y -+CONFIG_MTD_RAW_NAND=y -+CONFIG_NAND_BRCMNAND=y -+CONFIG_SYS_NAND_ONFI_DETECTION=y -+CONFIG_CMD_NAND=y -+CONFIG_DM_SERIAL=y -+CONFIG_SYS_NS16550=y -+# CONFIG_NET is not set -+# CONFIG_EFI_LOADER is not set ---- a/doc/board/broadcom/index.rst -+++ b/doc/board/broadcom/index.rst -@@ -9,3 +9,4 @@ Broadcom - - bcm7xxx - raspberrypi -+ northstar ---- /dev/null -+++ b/doc/board/broadcom/northstar.rst -@@ -0,0 +1,44 @@ -+.. SPDX-License-Identifier: GPL-2.0+ -+.. Copyright (C) 2023 Linus Walleij -+ -+Broadcom Northstar Boards -+========================= -+ -+This document describes how to use U-Boot on the Broadcom Northstar -+boards, comprised of the Cortex A9 ARM-based BCM470x and BCM5301x SoCs. These -+were introduced in 2012-2013 and some of them are also called StrataGX. -+ -+Northstar is part of the iProc SoC family. -+ -+A good overview of these boards can be found in Jon Mason's presentation -+"Enabling New Hardware in U-Boot" where the difference between Northstar -+and Northstar Plus and Northstar 2 (Aarch64) is addressed. -+ -+The ROM in the Northstar SoC will typically look into NOR flash memory -+for a boot loader, and the way this works is undocumented. It should be -+possible to execute U-Boot as the first binary from the NOR flash but -+this usage path is unexplored. Please add information if you know more. -+ -+D-Link Boards -+------------- -+ -+When we use U-Boot with D-Link routers, the NOR flash has a boot loader -+and web server that can re-flash the bigger NAND flash memory for object -+code in the SEAMA format, so on these platforms U-Boot is converted into -+a SEAMA binary and installed in the SoC using the flash tool resident in -+the NOR flash. Details can be found in the OpenWrt project codebase. -+ -+Configure -+--------- -+ -+.. code-block:: console -+ -+ $ make CROSS_COMPILE=${CROSS_COMPILE} bcmns_defconfig -+ -+Build -+----- -+ -+.. code-block:: console -+ -+ $ make CROSS_COMPILE=${CROSS_COMPILE} -+ $ ${CROSS_COMPILE}strip u-boot ---- /dev/null -+++ b/include/configs/bcmns.h -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+ -+#ifndef __BCM_NS_H -+#define __BCM_NS_H -+ -+#include -+ -+/* Physical Memory Map */ -+#define V2M_BASE 0x00000000 -+#define PHYS_SDRAM_1 V2M_BASE -+ -+#define CFG_SYS_SDRAM_BASE PHYS_SDRAM_1 -+ -+/* Called "periph_clk" in Linux, used by the global timer */ -+#define CFG_SYS_HZ_CLOCK 500000000 -+ -+/* Called "iprocslow" in Linux */ -+#define CFG_SYS_NS16550_CLK 125000000 -+ -+/* console configuration */ -+#define CONSOLE_ARGS "console_args=console=ttyS0,115200n8\0" -+#define MAX_CPUS "max_cpus=maxcpus=2\0" -+#define EXTRA_ARGS "extra_args=earlycon=uart8250,mmio32,0x18000300\0" -+ -+#define BASE_ARGS "${console_args} ${extra_args} ${pcie_args}" \ -+ " ${max_cpus} ${log_level} ${reserved_mem}" -+#define SETBOOTARGS "setbootargs=setenv bootargs " BASE_ARGS "\0" -+ -+#define KERNEL_LOADADDR_CFG \ -+ "loadaddr=0x01000000\0" \ -+ "dtb_loadaddr=0x02000000\0" -+ -+/* -+ * Hardcoded for the only boards we support, if you add more -+ * boards, add a more clever bootcmd! -+ */ -+#define NS_BOOTCMD "bootcmd_dlink_dir8xxl=seama 0x00fe0000; go 0x01000000" -+ -+#define ARCH_ENV_SETTINGS \ -+ CONSOLE_ARGS \ -+ MAX_CPUS \ -+ EXTRA_ARGS \ -+ KERNEL_LOADADDR_CFG \ -+ NS_BOOTCMD -+ -+#define CFG_EXTRA_ENV_SETTINGS \ -+ ARCH_ENV_SETTINGS -+ -+#endif /* __BCM_NS_H */ diff --git a/package/boot/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-envtools/files/mediatek_filogic index b4957c212b..4c483ca614 100644 --- a/package/boot/uboot-envtools/files/mediatek_filogic +++ b/package/boot/uboot-envtools/files/mediatek_filogic @@ -69,6 +69,7 @@ qihoo,360t7|\ tplink,tl-xdr4288|\ tplink,tl-xdr6086|\ tplink,tl-xdr6088|\ +xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-ubootmod) . /lib/upgrade/nand.sh @@ -86,6 +87,11 @@ glinet,gl-mt6000) glinet,gl-mt3000) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x20000" ;; +jdcloud,re-cp-03) + local envdev=$(find_mmc_part "ubootenv" "mmcblk0") + ubootenv_add_uci_config "$envdev" "0x0" "0x40000" "0x40000" "1" + ubootenv_add_uci_config "$envdev" "0x40000" "0x40000" "0x40000" "1" + ;; mercusys,mr90x-v1|\ routerich,ax3000) local envdev=/dev/mtd$(find_mtd_index "u-boot-env") @@ -94,7 +100,7 @@ routerich,ax3000) ubnt,unifi-6-plus) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x10000" ;; -xiaomi,mi-router-wr30u-112m-nmbm|\ +xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,redmi-router-ax6000-stock) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x20000" diff --git a/package/boot/uboot-envtools/files/mediatek_mt7622 b/package/boot/uboot-envtools/files/mediatek_mt7622 index e01dcc4fef..fdf0d331fc 100644 --- a/package/boot/uboot-envtools/files/mediatek_mt7622 +++ b/package/boot/uboot-envtools/files/mediatek_mt7622 @@ -12,6 +12,10 @@ touch /etc/config/ubootenv board=$(board_name) case "$board" in +dlink,eagle-pro-ai-m32-a1|\ +dlink,eagle-pro-ai-r32-a1) + ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x2000" "0x2000" + ;; linksys,e8450-ubi) ubootenv_add_uci_config "/dev/ubi0_0" "0x0" "0x1f000" "0x1f000" "1" ubootenv_add_uci_config "/dev/ubi0_1" "0x0" "0x1f000" "0x1f000" "1" diff --git a/package/boot/uboot-envtools/files/qualcommax_ipq807x b/package/boot/uboot-envtools/files/qualcommax_ipq807x index 761d5dfcc9..bcedfd9adc 100644 --- a/package/boot/uboot-envtools/files/qualcommax_ipq807x +++ b/package/boot/uboot-envtools/files/qualcommax_ipq807x @@ -29,6 +29,12 @@ edimax,cax1800) [ -n "$idx" ] && \ ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x20000" ;; +linksys,mx4200v1|\ +linksys,mx4200v2) + idx="$(find_mtd_index u_env)" + [ -n "$idx" ] && \ + ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" "2" + ;; redmi,ax6|\ xiaomi,ax3600|\ xiaomi,ax9000) diff --git a/package/boot/uboot-mediatek/Makefile b/package/boot/uboot-mediatek/Makefile index a9e6d35f00..8c0419f90c 100644 --- a/package/boot/uboot-mediatek/Makefile +++ b/package/boot/uboot-mediatek/Makefile @@ -322,6 +322,18 @@ define U-Boot/mt7981_qihoo_360t7 DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3 endef +define U-Boot/mt7981_xiaomi_mi-router-ax3000t + NAME:=Xiaomi Router AX3000T + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=xiaomi_mi-router-ax3000t-ubootmod + UBOOT_CONFIG:=mt7981_xiaomi_mi-router-ax3000t + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=spim-nand + BL2_SOC:=mt7981 + BL2_DDRTYPE:=ddr3 + DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3 +endef + define U-Boot/mt7981_xiaomi_mi-router-wr30u NAME:=Xiaomi Router WR30U BUILD_SUBTARGET:=filogic @@ -407,6 +419,18 @@ define U-Boot/mt7986_glinet_gl-mt6000 DEPENDS:=+trusted-firmware-a-mt7986-emmc-ddr4 endef +define U-Boot/mt7986_jdcloud_re-cp-03 + NAME:=JDCloud RE-CP-03 + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=jdcloud_re-cp-03 + UBOOT_CONFIG:=mt7986a_jdcloud_re-cp-03 + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=emmc + BL2_SOC:=mt7986 + BL2_DDRTYPE:=ddr4 + DEPENDS:=+trusted-firmware-a-mt7986-emmc-ddr4 +endef + define U-Boot/mt7986_tplink_tl-xdr4288 NAME:=TP-LINK TL-XDR4288 BUILD_SUBTARGET:=filogic @@ -556,12 +580,14 @@ UBOOT_TARGETS := \ mt7981_rfb-sd \ mt7981_rfb-snfi \ mt7981_qihoo_360t7 \ + mt7981_xiaomi_mi-router-ax3000t \ mt7981_xiaomi_mi-router-wr30u \ mt7986_bananapi_bpi-r3-emmc \ mt7986_bananapi_bpi-r3-sdmmc \ mt7986_bananapi_bpi-r3-snand \ mt7986_bananapi_bpi-r3-nor \ mt7986_glinet_gl-mt6000 \ + mt7986_jdcloud_re-cp-03 \ mt7986_tplink_tl-xdr4288 \ mt7986_tplink_tl-xdr6086 \ mt7986_tplink_tl-xdr6088 \ diff --git a/package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch b/package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch new file mode 100644 index 0000000000..e0f3a6e235 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch @@ -0,0 +1,324 @@ +--- /dev/null ++++ b/configs/mt7986a_jdcloud_re-cp-03_defconfig +@@ -0,0 +1,112 @@ ++CONFIG_ARM=y ++CONFIG_SYS_HAS_NONCACHED_MEMORY=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x40000 ++CONFIG_ENV_OFFSET=0x400000 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-jdcloud_re-cp-03" ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_TARGET_MT7986=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_ENV_OFFSET_REDUND=0x440000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7986a-jdcloud_re-cp-03.dtb" ++CONFIG_LOGLEVEL=7 ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_LOG=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_HUSH_PARSER=y ++CONFIG_CMD_CPU=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_PWM=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_LINK_LOCAL=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_UUID=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_EXT4=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_CMD_FS_UUID=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_DEFAULT_ENV_FILE="jdcloud_re-cp-03_env" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_NETCONSOLE=y ++CONFIG_USE_IPADDR=y ++CONFIG_IPADDR="192.168.1.1" ++CONFIG_USE_SERVERIP=y ++CONFIG_SERVERIP="192.168.1.254" ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_CLK=y ++CONFIG_GPIO_HOG=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_MDIO=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_DM_PWM=y ++CONFIG_PWM_MTK=y ++CONFIG_RAM=y ++CONFIG_SCSI=y ++CONFIG_DM_SCSI=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_LMB_MAX_REGIONS=64 +--- /dev/null ++++ b/arch/arm/dts/mt7986a-jdcloud_re-cp-03.dts +@@ -0,0 +1,148 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++/dts-v1/; ++#include ++#include "mt7986.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "JDCloud RE-CP-03"; ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb"; ++ ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x40000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ button-joylink { ++ label = "joylink"; ++ linux,code = ; ++ gpios = <&gpio 10 GPIO_ACTIVE_LOW>; ++ }; ++ ++ button-reset { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&gpio 9 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ label = "blue:status"; ++ gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ ++ led-1 { ++ label = "red:status"; ++ gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led-2 { ++ label = "green:status"; ++ gpios = <&gpio 12 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ }; ++ }; ++ ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "2500base-x"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ }; ++}; ++ ++&mmc0 { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ max-frequency = <200000000>; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_51"; ++ }; ++ ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-dsl { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; ++ }; ++ ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; +--- /dev/null ++++ b/jdcloud_re-cp-03_env +@@ -0,0 +1,55 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=root=/dev/mmcblk0p65 ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_emmc ; fi ++bootconf=config-1 ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-jdcloud_re-cp-03-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-jdcloud_re-cp-03-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-jdcloud_re-cp-03-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-jdcloud_re-cp-03-squashfs-sysupgrade.itb ++bootled_pwr=red:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from eMMC.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from eMMC.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to eMMC.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to eMMC.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to eMMC.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to eMMC.=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=led $bootled_pwr on ; run emmc_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=led $bootled_rec on ; run emmc_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_emmc=run boot_production ; run boot_recovery ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_production=tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run emmc_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run emmc_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run emmc_write_fip ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run emmc_write_bl2 ++boot_tftp=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++mmc_write_vol=imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc erase 0x$part_addr 0x$image_size && mmc write $loadaddr 0x$part_addr 0x$image_size ++mmc_read_vol=mmc read $loadaddr $part_addr 0x100 && imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc read $loadaddr 0x$part_addr 0x$image_size && setexpr filesize $image_size * 0x200 ++part_default=production ++part_recovery=recovery ++reset_factory=eraseenv && reset ++emmc_read_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_read_vol ++emmc_read_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_read_vol ++emmc_write_bl2=mmc partconf 0 1 1 1 && mmc erase 0x0 0x400 && mmc write $fileaddr 0x0 0x400 ; mmc partconf 0 1 1 0 ++emmc_write_fip=mmc erase 0x3400 0x2000 && mmc write $fileaddr 0x3400 0x2000 && mmc erase 0x2000 0x800 ++emmc_write_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_write_vol ++emmc_write_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_write_vol ++_init_env=setenv _init_env ; setenv _create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" diff --git a/package/boot/uboot-mediatek/patches/440-add-xiaomi_mi-router-ax3000t.patch b/package/boot/uboot-mediatek/patches/440-add-xiaomi_mi-router-ax3000t.patch new file mode 100644 index 0000000000..9b50166a94 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/440-add-xiaomi_mi-router-ax3000t.patch @@ -0,0 +1,414 @@ +--- /dev/null ++++ b/configs/mt7981_xiaomi_mi-router-ax3000t_defconfig +@@ -0,0 +1,163 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TARGET_MT7981=y ++CONFIG_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_SYS_HAS_NONCACHED_MEMORY=y ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7981_xiaomi_mi-router-ax3000t" ++CONFIG_DEFAULT_ENV_FILE="xiaomi_mi-router-ax3000t_env" ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7981_xiaomi_mi-router-ax3000t.dtb" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_SMBIOS_PRODUCT_NAME="" ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_CFB_CONSOLE_ANSI=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_GPIO_HOG=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_FIT=y ++CONFIG_FIT_ENABLE_SHA256_SUPPORT=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7981> " ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_BOOTP=y ++CONFIG_CMD_BUTTON=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_CPU=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_ECHO=y ++CONFIG_CMD_ENV_READMEM=y ++CONFIG_CMD_ERASEENV=y ++# CONFIG_CMD_EXT4 is not set ++# CONFIG_CMD_FAT is not set ++CONFIG_CMD_FDT=y ++# CONFIG_CMD_FS_GENERIC is not set ++# CONFIG_CMD_FS_UUID is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_ITEST=y ++CONFIG_CMD_LED=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_LINK_LOCAL=y ++# CONFIG_CMD_MBR is not set ++CONFIG_CMD_MTD=y ++# CONFIG_CMD_PCI is not set ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++# CONFIG_CMD_PWM is not set ++CONFIG_CMD_SMC=y ++CONFIG_CMD_TFTPBOOT=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_CMD_UBIFS=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_SETEXPR=y ++CONFIG_CMD_SLEEP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_SOURCE=y ++CONFIG_CMD_STRINGS=y ++# CONFIG_CMD_USB is not set ++# CONFIG_CMD_FLASH is not set ++CONFIG_CMD_UUID=y ++CONFIG_DISPLAY_CPUINFO=y ++CONFIG_DM_MTD=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++# CONFIG_DM_USB is not set ++# CONFIG_DM_PWM is not set ++# CONFIG_PWM_MTK is not set ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_PARTITION_UUIDS=y ++CONFIG_NETCONSOLE=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DM_GPIO=y ++# CONFIG_DM_SCSI is not set ++# CONFIG_AHCI is not set ++CONFIG_PHY=y ++# CONFIG_PHY_MTK_TPHY is not set ++CONFIG_PHY_FIXED=y ++CONFIG_MTK_AHCI=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++# CONFIG_PCI is not set ++# CONFIG_MMC is not set ++# CONFIG_DM_MMC is not set ++CONFIG_MTD=y ++CONFIG_MTD_UBI_FASTMAP=y ++# CONFIG_DM_PCI is not set ++# CONFIG_PCIE_MEDIATEK is not set ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPI_NAND=y ++CONFIG_MTK_SPI_NAND_MTD=y ++CONFIG_SYSRESET_WATCHDOG=y ++CONFIG_WDT_MTK=y ++CONFIG_LZO=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_RANDOM_UUID=y ++CONFIG_REGEX=y ++# CONFIG_USB is not set ++# CONFIG_USB_HOST is not set ++# CONFIG_USB_XHCI_HCD is not set ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_STORAGE is not set ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_UBI=y ++CONFIG_ENV_UBI_PART="ubi" ++CONFIG_ENV_SIZE=0x1f000 ++CONFIG_ENV_SIZE_REDUND=0x1f000 ++CONFIG_ENV_UBI_VOLUME="ubootenv" ++CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTK_SPIM=y ++CONFIG_CMD_NAND=y ++CONFIG_CMD_NAND_TRIMFFS=y ++CONFIG_LMB_MAX_REGIONS=64 ++CONFIG_USE_IPADDR=y ++CONFIG_IPADDR="192.168.1.1" ++CONFIG_USE_SERVERIP=y ++CONFIG_SERVERIP="192.168.1.254" +--- /dev/null ++++ b/arch/arm/dts/mt7981_xiaomi_mi-router-ax3000t.dts +@@ -0,0 +1,187 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "Xiaomi Router AX3000T"; ++ compatible = "mediatek,mt7981", "mediatek,mt7981-rfb"; ++ ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x10000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ reset { ++ label = "reset"; ++ gpios = <&gpio 1 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ }; ++ ++ mesh { ++ label = "mesh"; ++ gpios = <&gpio 0 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ linux,input-type = ; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_status_blue { ++ label = "blue:status"; ++ gpios = <&gpio 9 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led_status_yellow { ++ label = "yellow:status"; ++ gpios = <&gpio 10 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&uart0 { ++ mediatek,force-highspeed; ++ status = "okay"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "2500base-x"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_1"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nand@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x00 0x100000>; ++ }; ++ ++ partition@100000 { ++ label = "Nvram"; ++ reg = <0x100000 0x40000>; ++ }; ++ ++ partition@140000 { ++ label = "Bdata"; ++ reg = <0x140000 0x40000>; ++ }; ++ ++ partition@180000 { ++ label = "factory"; ++ reg = <0x180000 0x200000>; ++ }; ++ ++ partition@380000 { ++ label = "fip"; ++ reg = <0x380000 0x200000>; ++ }; ++ ++ partition@580000 { ++ label = "crash"; ++ reg = <0x580000 0x40000>; ++ }; ++ ++ partition@5c0000 { ++ label = "crash_log"; ++ reg = <0x5c0000 0x40000>; ++ }; ++ ++ partition@600000 { ++ label = "ubi"; ++ reg = <0x600000 0x7000000>; ++ }; ++ ++ partition@7600000 { ++ label = "KF"; ++ reg = <0x7600000 0x40000>; ++ }; ++ }; ++ }; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; +--- /dev/null ++++ b/xiaomi_mi-router-ax3000t_env +@@ -0,0 +1,55 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=console=ttyS0,115200n8 console_msg_format=syslog ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi ++bootconf=config-1 ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-squashfs-sysupgrade.itb ++bootled_pwr=yellow:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from NAND.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from NAND.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to NAND.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to NAND.=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=led $bootled_pwr on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=led $bootled_rec on ; run ubi_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_ubi=run boot_production ; run boot_recovery ; run boot_tftp_forever ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_recovery=tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run ubi_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_production=tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run ubi_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run mtd_write_fip && run reset_factory ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run mtd_write_bl2 ++reset_factory=ubi part ubi ; mw $loadaddr 0x0 0x800 ; ubi write $loadaddr ubootenv 0x800 ; ubi write $loadaddr ubootenv2 0x800 ++mtd_write_fip=mtd erase fip && mtd write fip $loadaddr ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x100000 dynamic 0 || run ubi_format ; ubi check ubootenv2 || ubi create ubootenv2 0x100000 dynamic 1 || run ubi_format ++ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset ++ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi ++ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs ++ubi_read_recovery=ubi check recovery && ubi read $loadaddr recovery ++ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic 2 && ubi write $loadaddr fit $filesize ++ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic 3 && ubi write $loadaddr recovery $filesize ++_init_env=setenv _init_env ; run ubi_create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" diff --git a/package/boot/uboot-rockchip/Makefile b/package/boot/uboot-rockchip/Makefile index 1dad3c1e1c..71eac09d98 100644 --- a/package/boot/uboot-rockchip/Makefile +++ b/package/boot/uboot-rockchip/Makefile @@ -5,9 +5,9 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk -PKG_VERSION:=2023.07.02 +PKG_VERSION:=2024.01 PKG_RELEASE:=1 -PKG_HASH:=6b6a48581c14abb0f95bd87c1af4d740922406d7b801002a9f94727fdde021d5 +PKG_HASH:=b99611f1ed237bf3541bdc8434b68c96a6e05967061f992443cb30aabebef5b3 PKG_MAINTAINER:=Tobias Maedel diff --git a/package/boot/uboot-rockchip/patches/100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch b/package/boot/uboot-rockchip/patches/100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch deleted file mode 100644 index 487e6afda8..0000000000 --- a/package/boot/uboot-rockchip/patches/100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch +++ /dev/null @@ -1,594 +0,0 @@ -From 89afb631d965292aaf433806d8224b53d9e74036 Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Sat, 20 May 2023 18:50:38 +0800 -Subject: [PATCH] rockchip: rk3328: Add support for Orange Pi R1 Plus - -Orange Pi R1 Plus is a Rockchip RK3328 based SBC by Xunlong. - -This device is similar to the NanoPi R2S, and has a 16MB -SPI NOR (mx25l12805d). The reset button is changed to -directly reset the power supply, another detail is that -both network ports have independent MAC addresses. - -The device tree and description are taken from kernel v6.3-rc1. - -Reviewed-by: Kever Yang -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - .../dts/rk3328-orangepi-r1-plus-u-boot.dtsi | 46 +++ - arch/arm/dts/rk3328-orangepi-r1-plus.dts | 373 ++++++++++++++++++ - board/rockchip/evb_rk3328/MAINTAINERS | 6 + - configs/orangepi-r1-plus-rk3328_defconfig | 114 ++++++ - 5 files changed, 540 insertions(+) - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus.dts - create mode 100644 configs/orangepi-r1-plus-rk3328_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -125,6 +125,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3328) += \ - rk3328-evb.dtb \ - rk3328-nanopi-r2c.dtb \ - rk3328-nanopi-r2s.dtb \ -+ rk3328-orangepi-r1-plus.dtb \ - rk3328-roc-cc.dtb \ - rk3328-rock64.dtb \ - rk3328-rock-pi-e.dtb ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi -@@ -0,0 +1,46 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd -+ * (C) Copyright 2020 David Bauer -+ */ -+ -+#include "rk3328-u-boot.dtsi" -+#include "rk3328-sdram-ddr4-666.dtsi" -+/ { -+ chosen { -+ u-boot,spl-boot-order = "same-as-spl", &sdmmc, &emmc; -+ }; -+}; -+ -+&gpio0 { -+ bootph-pre-ram; -+}; -+ -+&pinctrl { -+ bootph-pre-ram; -+}; -+ -+&sdmmc0m1_pin { -+ bootph-pre-ram; -+}; -+ -+&pcfg_pull_up_4ma { -+ bootph-pre-ram; -+}; -+ -+/* Need this and all the pinctrl/gpio stuff above to set pinmux */ -+&vcc_sd { -+ bootph-pre-ram; -+}; -+ -+&gmac2io { -+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+}; -+ -+&spi0 { -+ spi_flash: spiflash@0 { -+ bootph-all; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus.dts -@@ -0,0 +1,373 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Based on rk3328-nanopi-r2s.dts, which is: -+ * Copyright (c) 2020 David Bauer -+ */ -+ -+/dts-v1/; -+ -+#include -+#include -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Xunlong Orange Pi R1 Plus"; -+ compatible = "xunlong,orangepi-r1-plus", "rockchip,rk3328"; -+ -+ aliases { -+ ethernet1 = &rtl8153; -+ mmc0 = &sdmmc; -+ }; -+ -+ chosen { -+ stdout-path = "serial2:1500000n8"; -+ }; -+ -+ gmac_clk: gmac-clock { -+ compatible = "fixed-clock"; -+ clock-frequency = <125000000>; -+ clock-output-names = "gmac_clkin"; -+ #clock-cells = <0>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; -+ pinctrl-names = "default"; -+ -+ led-0 { -+ function = LED_FUNCTION_LAN; -+ color = ; -+ gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-1 { -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led-2 { -+ function = LED_FUNCTION_WAN; -+ color = ; -+ gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&sdmmc0m1_pin>; -+ pinctrl-names = "default"; -+ regulator-name = "vcc_sd"; -+ regulator-boot-on; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ vcc_sys: vcc-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ vdd_5v_lan: vdd-5v-lan-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; -+ pinctrl-0 = <&lan_vdd_pin>; -+ pinctrl-names = "default"; -+ regulator-name = "vdd_5v_lan"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&display_subsystem { -+ status = "disabled"; -+}; -+ -+&gmac2io { -+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; -+ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; -+ clock_in_out = "input"; -+ phy-handle = <&rtl8211e>; -+ phy-mode = "rgmii"; -+ phy-supply = <&vcc_io>; -+ pinctrl-0 = <&rgmiim1_pins>; -+ pinctrl-names = "default"; -+ snps,aal; -+ rx_delay = <0x18>; -+ tx_delay = <0x24>; -+ status = "okay"; -+ -+ mdio { -+ compatible = "snps,dwmac-mdio"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ rtl8211e: ethernet-phy@1 { -+ reg = <1>; -+ pinctrl-0 = <ð_phy_reset_pin>; -+ pinctrl-names = "default"; -+ reset-assert-us = <10000>; -+ reset-deassert-us = <50000>; -+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: pmic@18 { -+ compatible = "rockchip,rk805"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio1>; -+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ pinctrl-0 = <&pmic_int_l>; -+ pinctrl-names = "default"; -+ rockchip,system-power-controller; -+ wakeup-source; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_sys>; -+ -+ regulators { -+ vdd_log: DCDC_REG1 { -+ regulator-name = "vdd_log"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-ramp-delay = <12500>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: DCDC_REG2 { -+ regulator-name = "vdd_arm"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-ramp-delay = <12500>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: DCDC_REG4 { -+ regulator-name = "vcc_io"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcc_18: LDO_REG1 { -+ regulator-name = "vcc_18"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc18_emmc: LDO_REG2 { -+ regulator-name = "vcc18_emmc"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: LDO_REG3 { -+ regulator-name = "vdd_10"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&io_domains { -+ pmuio-supply = <&vcc_io>; -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc18_emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vcc_io>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ gmac2io { -+ eth_phy_reset_pin: eth-phy-reset-pin { -+ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; -+ }; -+ }; -+ -+ leds { -+ lan_led_pin: lan-led-pin { -+ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ sys_led_pin: sys-led-pin { -+ rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wan_led_pin: wan-led-pin { -+ rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ lan { -+ lan_vdd_pin: lan-vdd-pin { -+ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+}; -+ -+&pwm2 { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ disable-wp; -+ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; -+ pinctrl-names = "default"; -+ vmmc-supply = <&vcc_sd>; -+ status = "okay"; -+}; -+ -+&spi0 { -+ status = "okay"; -+ -+ flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-max-frequency = <50000000>; -+ }; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&u2phy { -+ status = "okay"; -+}; -+ -+&u2phy_host { -+ status = "okay"; -+}; -+ -+&u2phy_otg { -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ dr_mode = "host"; -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* Second port is for USB 3.0 */ -+ rtl8153: device@2 { -+ compatible = "usbbda,8153"; -+ reg = <2>; -+ }; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; ---- a/board/rockchip/evb_rk3328/MAINTAINERS -+++ b/board/rockchip/evb_rk3328/MAINTAINERS -@@ -18,6 +18,12 @@ F: configs/nanopi-r2s-rk3328_defcon - F: arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi - F: arch/arm/dts/rk3328-nanopi-r2s.dts - -+ORANGEPI-R1-PLUS-RK3328 -+M: Tianling Shen -+S: Maintained -+F: configs/orangepi-r1-plus-rk3328_defconfig -+F: arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi -+ - ROC-RK3328-CC - M: Loic Devulder - M: Chen-Yu Tsai ---- /dev/null -+++ b/configs/orangepi-r1-plus-rk3328_defconfig -@@ -0,0 +1,114 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00200000 -+CONFIG_SPL_GPIO=y -+CONFIG_NR_DRAM_BANKS=1 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000 -+CONFIG_ENV_OFFSET=0x3F8000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3328-orangepi-r1-plus" -+CONFIG_DM_RESET=y -+CONFIG_ROCKCHIP_RK3328=y -+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_TPL_LIBCOMMON_SUPPORT=y -+CONFIG_TPL_LIBGENERIC_SUPPORT=y -+CONFIG_SPL_DRIVERS_MISC=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_SPL_STACK=0x400000 -+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800 -+CONFIG_DEBUG_UART_BASE=0xFF130000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0x800800 -+CONFIG_DEBUG_UART=y -+# CONFIG_ANDROID_BOOT_IMAGE is not set -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-orangepi-r1-plus.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_MISC_INIT_R=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x2000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x2000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_I2C=y -+CONFIG_SPL_POWER=y -+CONFIG_SPL_ATF=y -+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y -+CONFIG_TPL_SYS_MALLOC_SIMPLE=y -+CONFIG_CMD_BOOTZ=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+# CONFIG_CMD_SETEXPR is not set -+CONFIG_CMD_TIME=y -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_TPL_OF_CONTROL=y -+CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_TPL_OF_PLATDATA=y -+CONFIG_ENV_IS_IN_MMC=y -+CONFIG_SYS_RELOC_GD_ENV_ADDR=y -+CONFIG_SYS_MMC_ENV_DEV=1 -+CONFIG_NET_RANDOM_ETHADDR=y -+CONFIG_TPL_DM=y -+CONFIG_REGMAP=y -+CONFIG_SPL_REGMAP=y -+CONFIG_TPL_REGMAP=y -+CONFIG_SYSCON=y -+CONFIG_SPL_SYSCON=y -+CONFIG_TPL_SYSCON=y -+CONFIG_CLK=y -+CONFIG_SPL_CLK=y -+CONFIG_FASTBOOT_BUF_ADDR=0x800800 -+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_SF_DEFAULT_SPEED=20000000 -+CONFIG_SPI_FLASH_GIGADEVICE=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PINCTRL=y -+CONFIG_SPL_PINCTRL=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR=y -+CONFIG_REGULATOR_PWM=y -+CONFIG_DM_REGULATOR_FIXED=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_RAM=y -+CONFIG_SPL_RAM=y -+CONFIG_TPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_ROCKCHIP_SPI=y -+CONFIG_SYSINFO=y -+CONFIG_SYSRESET=y -+# CONFIG_TPL_SYSRESET is not set -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC2=y -+CONFIG_USB_DWC3=y -+# CONFIG_USB_DWC3_GADGET is not set -+CONFIG_USB_GADGET=y -+CONFIG_USB_GADGET_DWC2_OTG=y -+CONFIG_SPL_TINY_MEMSET=y -+CONFIG_TPL_TINY_MEMSET=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch b/package/boot/uboot-rockchip/patches/101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch deleted file mode 100644 index 56d36c74dc..0000000000 --- a/package/boot/uboot-rockchip/patches/101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch +++ /dev/null @@ -1,257 +0,0 @@ -From 408fd4570c0f1e6b1fe3722998394651144f2a29 Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Sat, 20 May 2023 18:52:14 +0800 -Subject: [PATCH] rockchip: rk3328: Add support for Orange Pi R1 Plus LTS - -The OrangePi R1 Plus LTS is a minor variant of OrangePi R1 Plus with -the on-board NIC chip changed from rtl8211e to yt8531c, and RAM type -changed from DDR4 to LPDDR3. - -The device tree is taken from kernel v6.4-rc1. - -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - .../rk3328-orangepi-r1-plus-lts-u-boot.dtsi | 46 +++++++ - arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts | 40 ++++++ - board/rockchip/evb_rk3328/MAINTAINERS | 6 + - configs/orangepi-r1-plus-lts-rk3328_defconfig | 114 ++++++++++++++++++ - 5 files changed, 207 insertions(+) - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus-lts-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts - create mode 100644 configs/orangepi-r1-plus-lts-rk3328_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -126,6 +126,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3328) += \ - rk3328-nanopi-r2c.dtb \ - rk3328-nanopi-r2s.dtb \ - rk3328-orangepi-r1-plus.dtb \ -+ rk3328-orangepi-r1-plus-lts.dtb \ - rk3328-roc-cc.dtb \ - rk3328-rock64.dtb \ - rk3328-rock-pi-e.dtb ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus-lts-u-boot.dtsi -@@ -0,0 +1,46 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd -+ * (C) Copyright 2020 David Bauer -+ */ -+ -+#include "rk3328-u-boot.dtsi" -+#include "rk3328-sdram-lpddr3-666.dtsi" -+/ { -+ chosen { -+ u-boot,spl-boot-order = "same-as-spl", &sdmmc, &emmc; -+ }; -+}; -+ -+&gpio0 { -+ bootph-pre-ram; -+}; -+ -+&pinctrl { -+ bootph-pre-ram; -+}; -+ -+&sdmmc0m1_pin { -+ bootph-pre-ram; -+}; -+ -+&pcfg_pull_up_4ma { -+ bootph-pre-ram; -+}; -+ -+/* Need this and all the pinctrl/gpio stuff above to set pinmux */ -+&vcc_sd { -+ bootph-pre-ram; -+}; -+ -+&gmac2io { -+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+}; -+ -+&spi0 { -+ spi_flash: spiflash@0 { -+ bootph-all; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts -@@ -0,0 +1,40 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2016 Xunlong Software. Co., Ltd. -+ * (http://www.orangepi.org) -+ * -+ * Copyright (c) 2021-2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include "rk3328-orangepi-r1-plus.dts" -+ -+/ { -+ model = "Xunlong Orange Pi R1 Plus LTS"; -+ compatible = "xunlong,orangepi-r1-plus-lts", "rockchip,rk3328"; -+}; -+ -+&gmac2io { -+ phy-handle = <&yt8531c>; -+ tx_delay = <0x19>; -+ rx_delay = <0x05>; -+ -+ mdio { -+ /delete-node/ ethernet-phy@1; -+ -+ yt8531c: ethernet-phy@0 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ -+ motorcomm,clk-out-frequency-hz = <125000000>; -+ motorcomm,keep-pll-enabled; -+ motorcomm,auto-sleep-disabled; -+ -+ pinctrl-0 = <ð_phy_reset_pin>; -+ pinctrl-names = "default"; -+ reset-assert-us = <15000>; -+ reset-deassert-us = <50000>; -+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; ---- a/board/rockchip/evb_rk3328/MAINTAINERS -+++ b/board/rockchip/evb_rk3328/MAINTAINERS -@@ -24,6 +24,12 @@ S: Maintained - F: configs/orangepi-r1-plus-rk3328_defconfig - F: arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi - -+ORANGEPI-R1-PLUS-LTS-RK3328 -+M: Tianling Shen -+S: Maintained -+F: configs/orangepi-r1-plus-lts-rk3328_defconfig -+F: arch/arm/dts/rk3328-orangepi-r1-plus-lts-u-boot.dtsi -+ - ROC-RK3328-CC - M: Loic Devulder - M: Chen-Yu Tsai ---- /dev/null -+++ b/configs/orangepi-r1-plus-lts-rk3328_defconfig -@@ -0,0 +1,114 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00200000 -+CONFIG_SPL_GPIO=y -+CONFIG_NR_DRAM_BANKS=1 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000 -+CONFIG_ENV_OFFSET=0x3F8000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3328-orangepi-r1-plus-lts" -+CONFIG_DM_RESET=y -+CONFIG_ROCKCHIP_RK3328=y -+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_TPL_LIBCOMMON_SUPPORT=y -+CONFIG_TPL_LIBGENERIC_SUPPORT=y -+CONFIG_SPL_DRIVERS_MISC=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_SPL_STACK=0x400000 -+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800 -+CONFIG_DEBUG_UART_BASE=0xFF130000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0x800800 -+CONFIG_DEBUG_UART=y -+# CONFIG_ANDROID_BOOT_IMAGE is not set -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-orangepi-r1-plus-lts.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_MISC_INIT_R=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x2000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x2000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_I2C=y -+CONFIG_SPL_POWER=y -+CONFIG_SPL_ATF=y -+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y -+CONFIG_TPL_SYS_MALLOC_SIMPLE=y -+CONFIG_CMD_BOOTZ=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+# CONFIG_CMD_SETEXPR is not set -+CONFIG_CMD_TIME=y -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_TPL_OF_CONTROL=y -+CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_TPL_OF_PLATDATA=y -+CONFIG_ENV_IS_IN_MMC=y -+CONFIG_SYS_RELOC_GD_ENV_ADDR=y -+CONFIG_SYS_MMC_ENV_DEV=1 -+CONFIG_NET_RANDOM_ETHADDR=y -+CONFIG_TPL_DM=y -+CONFIG_REGMAP=y -+CONFIG_SPL_REGMAP=y -+CONFIG_TPL_REGMAP=y -+CONFIG_SYSCON=y -+CONFIG_SPL_SYSCON=y -+CONFIG_TPL_SYSCON=y -+CONFIG_CLK=y -+CONFIG_SPL_CLK=y -+CONFIG_FASTBOOT_BUF_ADDR=0x800800 -+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_SF_DEFAULT_SPEED=20000000 -+CONFIG_SPI_FLASH_GIGADEVICE=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PINCTRL=y -+CONFIG_SPL_PINCTRL=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR=y -+CONFIG_REGULATOR_PWM=y -+CONFIG_DM_REGULATOR_FIXED=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_RAM=y -+CONFIG_SPL_RAM=y -+CONFIG_TPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_ROCKCHIP_SPI=y -+CONFIG_SYSINFO=y -+CONFIG_SYSRESET=y -+# CONFIG_TPL_SYSRESET is not set -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC2=y -+CONFIG_USB_DWC3=y -+# CONFIG_USB_DWC3_GADGET is not set -+CONFIG_USB_GADGET=y -+CONFIG_USB_GADGET_DWC2_OTG=y -+CONFIG_SPL_TINY_MEMSET=y -+CONFIG_TPL_TINY_MEMSET=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch b/package/boot/uboot-rockchip/patches/103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch deleted file mode 100644 index 09cafb3227..0000000000 --- a/package/boot/uboot-rockchip/patches/103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch +++ /dev/null @@ -1,917 +0,0 @@ -From c84214aab0e4c5b2f619dd89655f27b3ae40e82b Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Tue, 30 May 2023 15:00:33 +0800 -Subject: [PATCH] rockchip: rk3568: Add support for FriendlyARM NanoPi R5S - -FriendlyARM NanoPi R5S is an open-sourced mini IoT gateway device. - -Board Specifications -- Rockchip RK3568 -- 2 or 4GB LPDDR4X -- 8GB or 16GB eMMC, SD card slot -- GbE LAN (Native) -- 2x 2.5G LAN (PCIe) -- M.2 Connector -- HDMI 2.0, MIPI DSI/CSI -- 2xUSB 3.0 Host -- USB Type C PD, 5V/9V/12V -- GPIO: 12-pin 0.5mm FPC connector - -The device tree is taken from kernel v6.4-rc1. - -Reviewed-by: Kever Yang -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi | 31 ++ - arch/arm/dts/rk3568-nanopi-r5s.dts | 136 +++++ - arch/arm/dts/rk3568-nanopi-r5s.dtsi | 590 +++++++++++++++++++++ - board/rockchip/evb_rk3568/MAINTAINERS | 8 + - configs/nanopi-r5s-rk3568_defconfig | 85 +++ - 6 files changed, 851 insertions(+) - create mode 100644 arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3568-nanopi-r5s.dts - create mode 100644 arch/arm/dts/rk3568-nanopi-r5s.dtsi - create mode 100644 configs/nanopi-r5s-rk3568_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3568) += \ - rk3566-anbernic-rgxx3.dtb \ - rk3566-radxa-cm3-io.dtb \ - rk3568-evb.dtb \ -+ rk3568-nanopi-r5s.dtb \ - rk3568-rock-3a.dtb - - dtb-$(CONFIG_ROCKCHIP_RK3588) += \ ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi -@@ -0,0 +1,31 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+#include "rk356x-u-boot.dtsi" -+ -+/ { -+ chosen { -+ stdout-path = &uart2; -+ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; -+ }; -+}; -+ -+&sdhci { -+ cap-mmc-highspeed; -+ mmc-ddr-1_8v; -+ mmc-hs200-1_8v; -+ mmc-hs400-1_8v; -+ mmc-hs400-enhanced-strobe; -+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; -+}; -+ -+&uart2 { -+ clock-frequency = <24000000>; -+ bootph-all; -+ status = "okay"; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5s.dts -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include "rk3568-nanopi-r5s.dtsi" -+ -+/ { -+ model = "FriendlyElec NanoPi R5S"; -+ compatible = "friendlyarm,nanopi-r5s", "rockchip,rk3568"; -+ -+ aliases { -+ ethernet0 = &gmac0; -+ }; -+ -+ gpio-leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lan1_led_pin>, <&lan2_led_pin>, <&power_led_pin>, <&wan_led_pin>; -+ -+ led-lan1 { -+ color = ; -+ function = LED_FUNCTION_LAN; -+ function-enumerator = <1>; -+ gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-lan2 { -+ color = ; -+ function = LED_FUNCTION_LAN; -+ function-enumerator = <2>; -+ gpios = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ power_led: led-power { -+ color = ; -+ function = LED_FUNCTION_POWER; -+ linux,default-trigger = "heartbeat"; -+ gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-wan { -+ color = ; -+ function = LED_FUNCTION_WAN; -+ gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; -+ -+&gmac0 { -+ assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; -+ assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>; -+ assigned-clock-rates = <0>, <125000000>; -+ clock_in_out = "output"; -+ phy-handle = <&rgmii_phy0>; -+ phy-mode = "rgmii"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&gmac0_miim -+ &gmac0_tx_bus2 -+ &gmac0_rx_bus2 -+ &gmac0_rgmii_clk -+ &gmac0_rgmii_bus>; -+ snps,reset-gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ /* Reset time is 15ms, 50ms for rtl8211f */ -+ snps,reset-delays-us = <0 15000 50000>; -+ tx_delay = <0x3c>; -+ rx_delay = <0x2f>; -+ status = "okay"; -+}; -+ -+&mdio0 { -+ rgmii_phy0: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ pinctrl-0 = <ð_phy0_reset_pin>; -+ pinctrl-names = "default"; -+ }; -+}; -+ -+&pcie2x1 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -+ -+&pcie30phy { -+ data-lanes = <1 2>; -+ status = "okay"; -+}; -+ -+&pcie3x1 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pcie3x2 { -+ num-lanes = <1>; -+ num-ib-windows = <8>; -+ num-ob-windows = <8>; -+ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ gmac0 { -+ eth_phy0_reset_pin: eth-phy0-reset-pin { -+ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ gpio-leds { -+ lan1_led_pin: lan1-led-pin { -+ rockchip,pins = <3 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ lan2_led_pin: lan2-led-pin { -+ rockchip,pins = <3 RK_PD7 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ power_led_pin: power-led-pin { -+ rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wan_led_pin: wan-led-pin { -+ rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5s.dtsi -@@ -0,0 +1,590 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include -+#include -+#include -+#include -+#include -+#include "rk3568.dtsi" -+ -+/ { -+ aliases { -+ mmc0 = &sdmmc0; -+ mmc1 = &sdhci; -+ }; -+ -+ chosen: chosen { -+ stdout-path = "serial2:1500000n8"; -+ }; -+ -+ hdmi-con { -+ compatible = "hdmi-connector"; -+ type = "a"; -+ -+ port { -+ hdmi_con_in: endpoint { -+ remote-endpoint = <&hdmi_out_con>; -+ }; -+ }; -+ }; -+ -+ vdd_usbc: vdd-usbc-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vdd_usbc"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ vcc3v3_sys: vcc3v3-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc3v3_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vdd_usbc>; -+ }; -+ -+ vcc5v0_sys: vcc5v0-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vdd_usbc>; -+ }; -+ -+ vcc3v3_pcie: vcc3v3-pcie-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc3v3_pcie"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; -+ startup-delay-us = <200000>; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ -+ vcc5v0_usb: vcc5v0-usb-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_usb"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vdd_usbc>; -+ }; -+ -+ vcc5v0_usb_host: vcc5v0-usb-host-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&vcc5v0_usb_host_en>; -+ regulator-name = "vcc5v0_usb_host"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vcc5v0_usb>; -+ }; -+ -+ vcc5v0_usb_otg: vcc5v0-usb-otg-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&vcc5v0_usb_otg_en>; -+ regulator-name = "vcc5v0_usb_otg"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vcc5v0_usb>; -+ }; -+ -+ pcie30_avdd0v9: pcie30-avdd0v9-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "pcie30_avdd0v9"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <900000>; -+ vin-supply = <&vcc3v3_sys>; -+ }; -+ -+ pcie30_avdd1v8: pcie30-avdd1v8-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "pcie30_avdd1v8"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ vin-supply = <&vcc3v3_sys>; -+ }; -+}; -+ -+&combphy0 { -+ status = "okay"; -+}; -+ -+&combphy1 { -+ status = "okay"; -+}; -+ -+&combphy2 { -+ status = "okay"; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_gpu>; -+ status = "okay"; -+}; -+ -+&hdmi { -+ avdd-0v9-supply = <&vdda0v9_image>; -+ avdd-1v8-supply = <&vcca1v8_image>; -+ status = "okay"; -+}; -+ -+&hdmi_in { -+ hdmi_in_vp0: endpoint { -+ remote-endpoint = <&vp0_out_hdmi>; -+ }; -+}; -+ -+&hdmi_out { -+ hdmi_out_con: endpoint { -+ remote-endpoint = <&hdmi_con_in>; -+ }; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ -+ vdd_cpu: regulator@1c { -+ compatible = "tcs,tcs4525"; -+ reg = <0x1c>; -+ fcs,suspend-voltage-selector = <1>; -+ regulator-name = "vdd_cpu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-ramp-delay = <2300>; -+ vin-supply = <&vcc5v0_sys>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ rk809: pmic@20 { -+ compatible = "rockchip,rk809"; -+ reg = <0x20>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ #clock-cells = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int>; -+ rockchip,system-power-controller; -+ vcc1-supply = <&vcc3v3_sys>; -+ vcc2-supply = <&vcc3v3_sys>; -+ vcc3-supply = <&vcc3v3_sys>; -+ vcc4-supply = <&vcc3v3_sys>; -+ vcc5-supply = <&vcc3v3_sys>; -+ vcc6-supply = <&vcc3v3_sys>; -+ vcc7-supply = <&vcc3v3_sys>; -+ vcc8-supply = <&vcc3v3_sys>; -+ vcc9-supply = <&vcc3v3_sys>; -+ wakeup-source; -+ -+ regulators { -+ vdd_logic: DCDC_REG1 { -+ regulator-name = "vdd_logic"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-init-microvolt = <900000>; -+ regulator-initial-mode = <0x2>; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <6001>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_gpu: DCDC_REG2 { -+ regulator-name = "vdd_gpu"; -+ regulator-always-on; -+ regulator-init-microvolt = <900000>; -+ regulator-initial-mode = <0x2>; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <6001>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-initial-mode = <0x2>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vdd_npu: DCDC_REG4 { -+ regulator-name = "vdd_npu"; -+ regulator-init-microvolt = <900000>; -+ regulator-initial-mode = <0x2>; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <6001>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_1v8: DCDC_REG5 { -+ regulator-name = "vcc_1v8"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdda0v9_image: LDO_REG1 { -+ regulator-name = "vdda0v9_image"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <950000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdda_0v9: LDO_REG2 { -+ regulator-name = "vdda_0v9"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <900000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdda0v9_pmu: LDO_REG3 { -+ regulator-name = "vdda0v9_pmu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <900000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <900000>; -+ }; -+ }; -+ -+ vccio_acodec: LDO_REG4 { -+ regulator-name = "vccio_acodec"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vccio_sd: LDO_REG5 { -+ regulator-name = "vccio_sd"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc3v3_pmu: LDO_REG6 { -+ regulator-name = "vcc3v3_pmu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcca_1v8: LDO_REG7 { -+ regulator-name = "vcca_1v8"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcca1v8_pmu: LDO_REG8 { -+ regulator-name = "vcca1v8_pmu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcca1v8_image: LDO_REG9 { -+ regulator-name = "vcca1v8_image"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_3v3: SWITCH_REG1 { -+ regulator-name = "vcc_3v3"; -+ regulator-always-on; -+ regulator-boot-on; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc3v3_sd: SWITCH_REG2 { -+ regulator-name = "vcc3v3_sd"; -+ regulator-always-on; -+ regulator-boot-on; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ }; -+ -+ }; -+}; -+ -+&i2c5 { -+ status = "okay"; -+ -+ hym8563: rtc@51 { -+ compatible = "haoyu,hym8563"; -+ reg = <0x51>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ #clock-cells = <0>; -+ clock-output-names = "rtcic_32kout"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hym8563_int>; -+ wakeup-source; -+ }; -+}; -+ -+&i2s0_8ch { -+ status = "okay"; -+}; -+ -+&pcie30phy { -+ data-lanes = <1 2>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ hym8563 { -+ hym8563_int: hym8563-int { -+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int: pmic-int { -+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ usb { -+ vcc5v0_usb_host_en: vcc5v0-usb-host-en { -+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ vcc5v0_usb_otg_en: vcc5v0-usb-otg-en { -+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&pmu_io_domains { -+ pmuio1-supply = <&vcc3v3_pmu>; -+ pmuio2-supply = <&vcc3v3_pmu>; -+ vccio1-supply = <&vccio_acodec>; -+ vccio3-supply = <&vccio_sd>; -+ vccio4-supply = <&vcc_1v8>; -+ vccio5-supply = <&vcc_3v3>; -+ vccio6-supply = <&vcc_1v8>; -+ vccio7-supply = <&vcc_3v3>; -+ status = "okay"; -+}; -+ -+&saradc { -+ vref-supply = <&vcca_1v8>; -+ status = "okay"; -+}; -+ -+&sdhci { -+ bus-width = <8>; -+ max-frequency = <200000000>; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>; -+ status = "okay"; -+}; -+ -+&sdmmc0 { -+ max-frequency = <150000000>; -+ no-sdio; -+ no-mmc; -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ vmmc-supply = <&vcc3v3_sd>; -+ vqmmc-supply = <&vccio_sd>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <1>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usb_host0_xhci { -+ extcon = <&usb2phy0>; -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host1_ehci { -+ status = "okay"; -+}; -+ -+&usb_host1_ohci { -+ status = "okay"; -+}; -+ -+&usb_host1_xhci { -+ status = "okay"; -+}; -+ -+&usb2phy0 { -+ status = "okay"; -+}; -+ -+&usb2phy0_host { -+ phy-supply = <&vcc5v0_usb_host>; -+ status = "okay"; -+}; -+ -+&usb2phy0_otg { -+ status = "okay"; -+}; -+ -+&usb2phy1 { -+ status = "okay"; -+}; -+ -+&usb2phy1_host { -+ phy-supply = <&vcc5v0_usb_otg>; -+ status = "okay"; -+}; -+ -+&usb2phy1_otg { -+ status = "okay"; -+}; -+ -+&vop { -+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; -+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&vp0 { -+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { -+ reg = ; -+ remote-endpoint = <&hdmi_in_vp0>; -+ }; -+}; ---- a/board/rockchip/evb_rk3568/MAINTAINERS -+++ b/board/rockchip/evb_rk3568/MAINTAINERS -@@ -7,6 +7,14 @@ F: configs/evb-rk3568_defconfig - F: arch/arm/dts/rk3568-evb-boot.dtsi - F: arch/arm/dts/rk3568-evb.dts - -+NANOPI-R5S -+M: Tianling Shen -+S: Maintained -+F: configs/nanopi-r5s-rk3568_defconfig -+F: arch/arm/dts/rk3568-nanopi-r5s.dts -+F: arch/arm/dts/rk3568-nanopi-r5s.dtsi -+F: arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi -+ - RADXA-CM3 - M: Jagan Teki - S: Maintained ---- /dev/null -+++ b/configs/nanopi-r5s-rk3568_defconfig -@@ -0,0 +1,85 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00a00000 -+CONFIG_SPL_LIBCOMMON_SUPPORT=y -+CONFIG_SPL_LIBGENERIC_SUPPORT=y -+CONFIG_NR_DRAM_BANKS=2 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3568-nanopi-r5s" -+CONFIG_ROCKCHIP_RK3568=y -+CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_SPL_SERIAL=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_TARGET_EVB_RK3568=y -+CONFIG_SPL_STACK=0x400000 -+CONFIG_DEBUG_UART_BASE=0xFE660000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0xc00800 -+CONFIG_DEBUG_UART=y -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-nanopi-r5s.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x4000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x4000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_ATF=y -+CONFIG_CMD_GPIO=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_I2C=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+CONFIG_CMD_PMIC=y -+CONFIG_CMD_REGULATOR=y -+# CONFIG_SPL_DOS_PARTITION is not set -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_OF_LIVE=y -+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_SPL_DM_WARN=y -+CONFIG_SPL_REGMAP=y -+CONFIG_SPL_SYSCON=y -+CONFIG_SPL_CLK=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MISC=y -+CONFIG_SUPPORT_EMMC_RPMB=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_SDMA=y -+CONFIG_MMC_SDHCI_ROCKCHIP=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PHY_ROCKCHIP_INNO_USB2=y -+CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y -+CONFIG_POWER_DOMAIN=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_SPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_SYSRESET=y -+CONFIG_SYSRESET_PSCI=y -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC3=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch b/package/boot/uboot-rockchip/patches/104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch deleted file mode 100644 index d1a5197e7d..0000000000 --- a/package/boot/uboot-rockchip/patches/104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 41538742491c46100f570680c02fbdd0d2b6b880 Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Tue, 30 May 2023 15:00:33 +0800 -Subject: [PATCH] rockchip: rk3568: Add support for FriendlyARM NanoPi R5C - -FriendlyARM NanoPi R5C is an open-sourced mini IoT gateway device. - -Specification: -- Rockchip RK3568 -- 1/4GB LPDDR4X RAM -- 8/32GB eMMC -- SD card slot -- M.2 Connector -- 2x USB 3.0 Port -- 2x 2500 Base-T (PCIe, r8125) -- HDMI 2.0 -- MIPI DSI/CSI -- USB Type C 5V - -The device tree is taken from kernel v6.4-rc1. - -Reviewed-by: Kever Yang -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi | 3 + - arch/arm/dts/rk3568-nanopi-r5c.dts | 112 +++++++++++++++++++++ - board/rockchip/evb_rk3568/MAINTAINERS | 7 ++ - configs/nanopi-r5c-rk3568_defconfig | 85 ++++++++++++++++ - 5 files changed, 208 insertions(+) - create mode 100644 arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3568-nanopi-r5c.dts - create mode 100644 configs/nanopi-r5c-rk3568_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3568) += \ - rk3566-anbernic-rgxx3.dtb \ - rk3566-radxa-cm3-io.dtb \ - rk3568-evb.dtb \ -+ rk3568-nanopi-r5c.dtb \ - rk3568-nanopi-r5s.dtb \ - rk3568-rock-3a.dtb - ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi -@@ -0,0 +1,3 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+ -+#include "rk3568-nanopi-r5s-u-boot.dtsi" ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5c.dts -@@ -0,0 +1,112 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include "rk3568-nanopi-r5s.dtsi" -+ -+/ { -+ model = "FriendlyElec NanoPi R5C"; -+ compatible = "friendlyarm,nanopi-r5c", "rockchip,rk3568"; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&reset_button_pin>; -+ -+ button-reset { -+ debounce-interval = <50>; -+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_LOW>; -+ label = "reset"; -+ linux,code = ; -+ }; -+ }; -+ -+ gpio-leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lan_led_pin>, <&power_led_pin>, <&wan_led_pin>, <&wlan_led_pin>; -+ -+ led-lan { -+ color = ; -+ function = LED_FUNCTION_LAN; -+ gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ power_led: led-power { -+ color = ; -+ function = LED_FUNCTION_POWER; -+ linux,default-trigger = "heartbeat"; -+ gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-wan { -+ color = ; -+ function = LED_FUNCTION_WAN; -+ gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-wlan { -+ color = ; -+ function = LED_FUNCTION_WLAN; -+ gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; -+ -+&pcie2x1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie20_reset_pin>; -+ reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -+ -+&pcie3x1 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pcie3x2 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ gpio-leds { -+ lan_led_pin: lan-led-pin { -+ rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ power_led_pin: power-led-pin { -+ rockchip,pins = <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wan_led_pin: wan-led-pin { -+ rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wlan_led_pin: wlan-led-pin { -+ rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pcie { -+ pcie20_reset_pin: pcie20-reset-pin { -+ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ rockchip-key { -+ reset_button_pin: reset-button-pin { -+ rockchip,pins = <4 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+}; ---- a/board/rockchip/evb_rk3568/MAINTAINERS -+++ b/board/rockchip/evb_rk3568/MAINTAINERS -@@ -7,6 +7,13 @@ F: configs/evb-rk3568_defconfig - F: arch/arm/dts/rk3568-evb-boot.dtsi - F: arch/arm/dts/rk3568-evb.dts - -+NANOPI-R5C -+M: Tianling Shen -+S: Maintained -+F: configs/nanopi-r5c-rk3568_defconfig -+F: arch/arm/dts/rk3568-nanopi-r5c.dts -+F: arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi -+ - NANOPI-R5S - M: Tianling Shen - S: Maintained ---- /dev/null -+++ b/configs/nanopi-r5c-rk3568_defconfig -@@ -0,0 +1,85 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00a00000 -+CONFIG_SPL_LIBCOMMON_SUPPORT=y -+CONFIG_SPL_LIBGENERIC_SUPPORT=y -+CONFIG_NR_DRAM_BANKS=2 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3568-nanopi-r5c" -+CONFIG_ROCKCHIP_RK3568=y -+CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_SPL_SERIAL=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_TARGET_EVB_RK3568=y -+CONFIG_SPL_STACK=0x400000 -+CONFIG_DEBUG_UART_BASE=0xFE660000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0xc00800 -+CONFIG_DEBUG_UART=y -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-nanopi-r5c.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x4000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x4000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_ATF=y -+CONFIG_CMD_GPIO=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_I2C=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+CONFIG_CMD_PMIC=y -+CONFIG_CMD_REGULATOR=y -+# CONFIG_SPL_DOS_PARTITION is not set -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_OF_LIVE=y -+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_SPL_DM_WARN=y -+CONFIG_SPL_REGMAP=y -+CONFIG_SPL_SYSCON=y -+CONFIG_SPL_CLK=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MISC=y -+CONFIG_SUPPORT_EMMC_RPMB=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_SDMA=y -+CONFIG_MMC_SDHCI_ROCKCHIP=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PHY_ROCKCHIP_INNO_USB2=y -+CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y -+CONFIG_POWER_DOMAIN=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_SPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_SYSRESET=y -+CONFIG_SYSRESET_PSCI=y -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC3=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch b/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch index 7d2161ae42..b467f48f72 100644 --- a/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch +++ b/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch @@ -12,8 +12,6 @@ Signed-off-by: Lu jicong arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi b/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi -index 17201bcf41..8b6c9059ab 100644 --- a/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi +++ b/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi @@ -4,4 +4,4 @@ diff --git a/package/devel/gdb/Makefile b/package/devel/gdb/Makefile index 3efbce28f4..cf897b79f2 100644 --- a/package/devel/gdb/Makefile +++ b/package/devel/gdb/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gdb -PKG_VERSION:=13.2 -PKG_RELEASE:=2 +PKG_VERSION:=14.1 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNU/gdb -PKG_HASH:=fd5bebb7be1833abdb6e023c2f498a354498281df9d05523d8915babeb893f0a +PKG_HASH:=d66df51276143451fcbff464cc8723d68f1e9df45a6a2d5635a54e71643edb80 PKG_BUILD_PARALLEL:=1 PKG_INSTALL:=1 @@ -33,7 +33,7 @@ endef define Package/gdb $(call Package/gdb/Default) TITLE:=GNU Debugger - DEPENDS+=+libreadline +libncurses +zlib +libgmp + DEPENDS+=+libreadline +libncurses +zlib +libgmp +libmpfr endef define Package/gdb/description @@ -64,8 +64,6 @@ CONFIGURE_ARGS+= \ --disable-sim \ --disable-werror \ --disable-source-highlight \ - --without-mpc \ - --without-mpfr \ --without-isl \ --without-xxhash \ --with-libgmp-prefix=$(STAGING_DIR)/usr diff --git a/package/devel/gdb/patches/110-shared_libgcc.patch b/package/devel/gdb/patches/110-shared_libgcc.patch index 44d4ffa77f..1a02ad1160 100644 --- a/package/devel/gdb/patches/110-shared_libgcc.patch +++ b/package/devel/gdb/patches/110-shared_libgcc.patch @@ -1,6 +1,6 @@ --- a/configure.ac +++ b/configure.ac -@@ -1435,13 +1435,13 @@ if test -z "$LD"; then +@@ -1400,13 +1400,13 @@ if test -z "$LD"; then fi fi @@ -17,7 +17,7 @@ AC_LANG_PUSH(C++) AC_LINK_IFELSE([AC_LANG_SOURCE([ #if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) -@@ -1838,7 +1838,7 @@ AC_ARG_WITH(stage1-ldflags, +@@ -1836,7 +1836,7 @@ AC_ARG_WITH(stage1-ldflags, # trust that they are doing what they want. if test "$with_static_standard_libraries" = yes -a "$stage1_libs" = "" \ -a "$have_static_libs" = yes; then @@ -26,7 +26,7 @@ fi]) AC_SUBST(stage1_ldflags) -@@ -1867,7 +1867,7 @@ AC_ARG_WITH(boot-ldflags, +@@ -1865,7 +1865,7 @@ AC_ARG_WITH(boot-ldflags, # statically. But if the user explicitly specified the libraries to # use, trust that they are doing what they want. if test "$poststage1_libs" = ""; then @@ -37,7 +37,7 @@ --- a/configure +++ b/configure -@@ -5442,14 +5442,14 @@ if test -z "$LD"; then +@@ -5413,14 +5413,14 @@ if test -z "$LD"; then fi fi @@ -56,7 +56,7 @@ ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -@@ -8440,7 +8440,7 @@ else +@@ -8464,7 +8464,7 @@ else # trust that they are doing what they want. if test "$with_static_standard_libraries" = yes -a "$stage1_libs" = "" \ -a "$have_static_libs" = yes; then @@ -65,7 +65,7 @@ fi fi -@@ -8476,7 +8476,7 @@ else +@@ -8500,7 +8500,7 @@ else # statically. But if the user explicitly specified the libraries to # use, trust that they are doing what they want. if test "$poststage1_libs" = ""; then diff --git a/package/devel/gdb/patches/130-gdb-ctrl-c.patch b/package/devel/gdb/patches/130-gdb-ctrl-c.patch index 8650ce844c..5272b7e969 100644 --- a/package/devel/gdb/patches/130-gdb-ctrl-c.patch +++ b/package/devel/gdb/patches/130-gdb-ctrl-c.patch @@ -24,7 +24,7 @@ Signed-off-by: Khem Raj --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc -@@ -5467,7 +5467,7 @@ linux_process_target::request_interrupt +@@ -5481,7 +5481,7 @@ linux_process_target::request_interrupt { /* Send a SIGINT to the process group. This acts just like the user typed a ^C on the controlling terminal. */ diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index ef1a456403..5806654ecf 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -6,9 +6,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git -PKG_SOURCE_DATE:=2023-11-10 -PKG_SOURCE_VERSION:=0c2e810e71ed0a59fb00246c7fa2c236ff67a0ee -PKG_MIRROR_HASH:=fc6016540bd2c67484952d0e4432d740f0e022d9b688e851bb6321def8d36844 +PKG_SOURCE_DATE:=2024-01-06 +PKG_SOURCE_VERSION:=71f45cff8944405b7cc2bf5c19df2bd8fe7f2421 +PKG_MIRROR_HASH:=90c3c1659c54cdb4685d0a71633746c1000230e459801eb8ce12c805a994cc37 PKG_FLAGS:=nonshared @@ -34,6 +34,7 @@ ALLWIFIBOARDS:= \ dynalink_dl-wrx36 \ edgecore_eap102 \ edimax_cax1800 \ + linksys_mx4200 \ netgear_rax120v2 \ netgear_wax218 \ netgear_wax620 \ @@ -83,7 +84,7 @@ define ipq-wifi-install-one $(call ipq-wifi-install-one-to,$(1),$(2),QCA9984/hw1.0),\ $(if $(filter $(suffix $(1)),.QCA99X0 .qca99x0),\ $(call ipq-wifi-install-one-to,$(1),$(2),QCA99X0/hw2.0),\ - $(if $(filter $(suffix $(1)),.IPQ8074 .ipq8074),\ + $(if $(filter $(suffix $(1)),.IPQ8074 .ipq8074 .ipq8174),\ $(call ipq-wifi-install-ath11-one-to,$(1),$(2),IPQ8074/hw2.0),\ $(if $(filter $(suffix $(1)),.QCN9074 .qcn9074),\ $(call ipq-wifi-install-ath11-one-to,$(1),$(2),QCN9074/hw1.0),\ @@ -144,6 +145,7 @@ $(eval $(call generate-ipq-wifi-package,compex_wpq873,Compex WPQ-873)) $(eval $(call generate-ipq-wifi-package,dynalink_dl-wrx36,Dynalink DL-WRX36)) $(eval $(call generate-ipq-wifi-package,edgecore_eap102,Edgecore EAP102)) $(eval $(call generate-ipq-wifi-package,edimax_cax1800,Edimax CAX1800)) +$(eval $(call generate-ipq-wifi-package,linksys_mx4200,Linksys MX4200)) $(eval $(call generate-ipq-wifi-package,netgear_rax120v2,Netgear RAX120v2)) $(eval $(call generate-ipq-wifi-package,netgear_wax218,Netgear WAX218)) $(eval $(call generate-ipq-wifi-package,netgear_wax620,Netgear WAX620)) diff --git a/package/firmware/linux-firmware/Makefile b/package/firmware/linux-firmware/Makefile index 79341c30cb..f7f1f978e3 100644 --- a/package/firmware/linux-firmware/Makefile +++ b/package/firmware/linux-firmware/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=linux-firmware PKG_VERSION:=20231211 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz diff --git a/package/firmware/linux-firmware/broadcom.mk b/package/firmware/linux-firmware/broadcom.mk index 4f64b423eb..088a2665cc 100644 --- a/package/firmware/linux-firmware/broadcom.mk +++ b/package/firmware/linux-firmware/broadcom.mk @@ -125,9 +125,15 @@ define Package/brcmfmac-nvram-43455-sdio/install $(LN) \ brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ $(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ 4\ Model\ B.txt + $(LN) \ + brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ + $(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.txt $(LN) \ brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ $(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ Compute\ Module\ 4.txt + $(LN) \ + brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ + $(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ 5\ Model\ B.txt $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/brcm/brcmfmac43455-sdio.MINIX-NEO\ Z83-4.txt \ $(1)/lib/firmware/brcm/ diff --git a/package/kernel/bcm27xx-gpu-fw/Makefile b/package/kernel/bcm27xx-gpu-fw/Makefile index b3323c8b28..048dd0d3a9 100644 --- a/package/kernel/bcm27xx-gpu-fw/Makefile +++ b/package/kernel/bcm27xx-gpu-fw/Makefile @@ -2,8 +2,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=bcm27xx-gpu-fw -PKG_VERSION:=2022-05-16 -PKG_RELEASE:=3673be308132de102fdff491d1333d9d0f823557 +PKG_VERSION:=2024-01-11 +PKG_RELEASE:=0968de28716a9b1f106b8492646d0ed0a2800152 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)/rpi-firmware-$(PKG_RELEASE) @@ -26,7 +26,7 @@ define Download/bootcode_bin FILE:=$(RPI_FIRMWARE_FILE)-bootcode.bin URL:=$(RPI_FIRMWARE_URL) URL_FILE:=bootcode.bin - HASH:=69309823da13dc96b89e3d82b44f820e4f84efa79d207adad2c8784559794f03 + HASH:=af603ebd97e7b692c30195563f7b25656eb05d57838cf1a715ebb470d1614ce4 endef $(eval $(call Download,bootcode_bin)) @@ -34,7 +34,7 @@ define Download/fixup_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup.dat - HASH:=921f56c62ad1995addb984b156c869202dc5d46bbe9ebcbd02c20f0def9058e3 + HASH:=c28ea955e672e374016dca61d63afa026490f0473a98115908586ab48e324aeb endef $(eval $(call Download,fixup_dat)) @@ -42,7 +42,7 @@ define Download/fixup_cd_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup_cd.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup_cd.dat - HASH:=83a985aa0d73844786f3b3bf674826c520212f6f72fc6a890f2ebb5f87de5d8c + HASH:=3cf1aef5f596ca106203ed5dac9ad45e85929ec55ce44c813588645e174442ec endef $(eval $(call Download,fixup_cd_dat)) @@ -50,7 +50,7 @@ define Download/fixup_x_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup_x.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup_x.dat - HASH:=8b00b00678adafe01e087240d156dbc87822e745b269be4f282596b69265cd1e + HASH:=56525c8feabde1ab86f36bb09bc55171659b2993f94132cf81ffc4293d62269d endef $(eval $(call Download,fixup_x_dat)) @@ -58,7 +58,7 @@ define Download/fixup4_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup4.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup4.dat - HASH:=ef2b5d2a0a95ca48e00a1ce78b7650ee9e947cc1c588704c8ae30c1623122e2f + HASH:=615f8595801bf52373039f73ad5ad9513f83400d355eb1b2c075c7ae907e927c endef $(eval $(call Download,fixup4_dat)) @@ -66,7 +66,7 @@ define Download/fixup4cd_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup4cd.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup4cd.dat - HASH:=83a985aa0d73844786f3b3bf674826c520212f6f72fc6a890f2ebb5f87de5d8c + HASH:=3cf1aef5f596ca106203ed5dac9ad45e85929ec55ce44c813588645e174442ec endef $(eval $(call Download,fixup4cd_dat)) @@ -74,7 +74,7 @@ define Download/fixup4x_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup4x.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup4x.dat - HASH:=a6c4e30ada5a00fe7de83c460638ca824647651bb4a3644b8c65d7ba1d9f2d2b + HASH:=6d27a4b8ecb78cef9e1f03751b4aaec5ce8749d36988f381145a8a41dbf164ae endef $(eval $(call Download,fixup4x_dat)) @@ -82,7 +82,7 @@ define Download/start_elf FILE:=$(RPI_FIRMWARE_FILE)-start.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start.elf - HASH:=5455c148f4b8b04c553809bd22b995ee49ba5279ca3848df8bde6f80a388f7e0 + HASH:=e8348e88522e7a1d0e2b0944ab66d7d8f4f30da98f326e2b3c123522e45f71b2 endef $(eval $(call Download,start_elf)) @@ -90,7 +90,7 @@ define Download/start_cd_elf FILE:=$(RPI_FIRMWARE_FILE)-start_cd.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start_cd.elf - HASH:=168c0a9178d5a3b4bd89ef770826a85b4ea3132560ba3600c212c0cec4c575c6 + HASH:=c9b4de3f12bec7808868b898c49f656b5378ddc315f12ccab83d6519bad51680 endef $(eval $(call Download,start_cd_elf)) @@ -98,7 +98,7 @@ define Download/start_x_elf FILE:=$(RPI_FIRMWARE_FILE)-start_x.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start_x.elf - HASH:=30c6a7f32a25185053ca3ca9e4bcfe932246ed42a1b7c37f8803209f93d86404 + HASH:=0b5c06c109984361eeed0ab14d146f686d8aa8da2025689b887e9cb098636db9 endef $(eval $(call Download,start_x_elf)) @@ -106,7 +106,7 @@ define Download/start4_elf FILE:=$(RPI_FIRMWARE_FILE)-start4.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start4.elf - HASH:=be8bbff41dba2749b7b0e812f0a9d87a9122d18508f7b5ff3cd20f303d15bc07 + HASH:=fedc4ecd72c9d21018e210240dcd2e41a8bb5f936fb5674c3351f2a447a22203 endef $(eval $(call Download,start4_elf)) @@ -114,7 +114,7 @@ define Download/start4cd_elf FILE:=$(RPI_FIRMWARE_FILE)-start4cd.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start4cd.elf - HASH:=000372e9cf6815ade595948dbd6328665f2a535eeee44e74b0ec8e56b6fbbf90 + HASH:=ea22282a77666801378137a651e7e0b17cc186f63cdbdc8b9bb98749cd12b256 endef $(eval $(call Download,start4cd_elf)) @@ -122,7 +122,7 @@ define Download/start4x_elf FILE:=$(RPI_FIRMWARE_FILE)-start4x.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start4x.elf - HASH:=48895858f7936570dfab44c67bdcb0357ac8fcd630162c36ac9ed8f2de85c038 + HASH:=c509e73a9cba7af3223dea885f58294bd04845e822aa3d6278500fa4dcdb112f endef $(eval $(call Download,start4x_elf)) diff --git a/package/kernel/linux/Makefile b/package/kernel/linux/Makefile index c88b5c1b31..6592b01678 100644 --- a/package/kernel/linux/Makefile +++ b/package/kernel/linux/Makefile @@ -58,7 +58,12 @@ define Package/kernel endef define Package/kernel/install - # nothing to do + $(INSTALL_DIR) $(1)/$(MODULES_SUBDIR) + $(INSTALL_DATA) $(LINUX_DIR)/modules.builtin $(1)/$(MODULES_SUBDIR) + $(SED) 's,.*/,,' $(1)/$(MODULES_SUBDIR)/modules.builtin + strings $(LINUX_DIR)/modules.builtin.modinfo | \ + grep -E -v "\.(file$(if CONFIG_MODULE_STRIPPED,|parmtype))=" | \ + tr '\n' '\0' > $(1)/$(MODULES_SUBDIR)/modules.builtin.modinfo endef define Package/kernel/extra_provides diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index f2acaa7439..58af180c28 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -359,8 +359,7 @@ define KernelPackage/fs-ksmbd DEPENDS:= \ +kmod-nls-base \ +kmod-nls-utf8 \ - +kmod-crypto-md4 \ - +kmod-crypto-md5 \ + +kmod-crypto-md5 \ +kmod-crypto-hmac \ +kmod-crypto-ecb \ +kmod-crypto-des \ diff --git a/package/kernel/linux/modules/leds.mk b/package/kernel/linux/modules/leds.mk index 24af1b7f61..60465a8ad5 100644 --- a/package/kernel/linux/modules/leds.mk +++ b/package/kernel/linux/modules/leds.mk @@ -261,3 +261,37 @@ define KernelPackage/input-leds/description endef $(eval $(call KernelPackage,input-leds)) + + +define KernelPackage/leds-lp55xx-common + SUBMENU:=$(LEDS_MENU) + TITLE:=LED common driver for LP5521/LP5523/LP55231/LP5562 controllers + DEPENDS:=+kmod-i2c-core + KCONFIG:=CONFIG_LEDS_LP55XX_COMMON + FILES:=$(LINUX_DIR)/drivers/leds/leds-lp55xx-common.ko + AUTOLOAD:=$(call AutoLoad,60,leds-lp55xx-common,1) +endef + +define KernelPackage/leds-lp55xx-common/description + This option enables support for Texas Instruments + LP5521/LP5523/LP55231/LP5562 common driver. +endef + +$(eval $(call KernelPackage,leds-lp55xx-common)) + + +define KernelPackage/leds-lp5562 + SUBMENU:=$(LEDS_MENU) + TITLE:=LED driver for LP5562 controllers + DEPENDS:=+kmod-i2c-core +kmod-leds-lp55xx-common + KCONFIG:=CONFIG_LEDS_LP5562 + FILES:=$(LINUX_DIR)/drivers/leds/leds-lp5562.ko + AUTOLOAD:=$(call AutoLoad,60,leds-lp5562,1) +endef + +define KernelPackage/leds-lp5562/description + This option enables support for Texas Instruments LP5562 + LED controllers. +endef + +$(eval $(call KernelPackage,leds-lp5562)) \ No newline at end of file diff --git a/package/kernel/linux/modules/netdevices.mk b/package/kernel/linux/modules/netdevices.mk index 46dcdfdef7..63f75e9591 100644 --- a/package/kernel/linux/modules/netdevices.mk +++ b/package/kernel/linux/modules/netdevices.mk @@ -380,9 +380,7 @@ define KernelPackage/phy-aquantia TITLE:=Aquantia Ethernet PHYs DEPENDS:=+kmod-libphy +kmod-hwmon-core +kmod-lib-crc-ccitt KCONFIG:=CONFIG_AQUANTIA_PHY - FILES:= \ - $(LINUX_DIR)/drivers/net/phy/aquantia.ko@lt6.1 \ - $(LINUX_DIR)/drivers/net/phy/aquantia/aquantia.ko@ge6.1 + FILES:=$(LINUX_DIR)/drivers/net/phy/aquantia/aquantia.ko AUTOLOAD:=$(call AutoLoad,18,aquantia,1) endef diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 1bf4db6e5f..49ffb219bc 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -19,6 +19,10 @@ wdev_tool() { ucode /usr/share/hostap/wdev.uc "$@" } +ubus_call() { + flock /var/run/hostapd.lock ubus call "$@" +} + drv_mac80211_init_device_config() { hostapd_common_add_device_config @@ -145,7 +149,7 @@ mac80211_hostapd_setup_base() { [ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \ channel_list="$channel" - [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" + [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" "$N" set_default noscan 0 @@ -327,6 +331,11 @@ mac80211_hostapd_setup_base() { [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))" + [ "$vht_oper_chwidth" -lt 2 ] && { + vht160=0 + short_gi_160=0 + } + mac80211_add_capabilities vht_capab $vht_cap \ RXLDPC:0x10::$rxldpc \ SHORT-GI-80:0x20::$short_gi_80 \ @@ -550,7 +559,7 @@ get_board_phy_name() ( local ref_path="$3" json_select "$key" - json_get_values path + json_get_vars path json_select .. [ "${ref_path%+*}" = "$path" ] && fallback_phy=$key @@ -582,7 +591,7 @@ rename_board_phy_by_name() ( json_load_file /etc/board.json json_select wlan json_select "${phy%.*}" || return 0 - json_get_values path + json_get_vars path prev_phy="$(iwinfo nl80211 phyname "path=$path${suffix:++$suffix}")" [ -n "$prev_phy" ] || return 0 @@ -898,7 +907,7 @@ wpa_supplicant_set_config() { ubus wait_for wpa_supplicant } - local supplicant_res="$(ubus call wpa_supplicant config_set "$data")" + local supplicant_res="$(ubus_call wpa_supplicant config_set "$data")" ret="$?" [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED @@ -908,12 +917,12 @@ wpa_supplicant_set_config() { hostapd_set_config() { [ -n "$hostapd_ctrl" ] || { - ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null + ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null return 0; } ubus wait_for hostapd - local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" + local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" ret="$?" [ "$ret" != 0 -o -z "$hostapd_res" ] && { wireless_setup_failed HOSTAPD_START_FAILED @@ -928,7 +937,7 @@ wpa_supplicant_start() { [ -n "$wpa_supp_init" ] || return 0 - ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null + ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null } mac80211_setup_supplicant() { @@ -1029,15 +1038,15 @@ mac80211_set_noscan() { } drv_mac80211_cleanup() { - hostapd_common_cleanup + : } mac80211_reset_config() { local phy="$1" hostapd_conf_file="/var/run/hostapd-$phy.conf" - ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null - ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null + ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null + ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null wdev_tool "$phy" set_config '{}' } diff --git a/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch index 54abb4d425..474fb3fdbe 100644 --- a/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch +++ b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch @@ -79,7 +79,7 @@ } --- a/drivers/net/wireless/ath/ath9k/common-debug.c +++ b/drivers/net/wireless/ath/ath9k/common-debug.c -@@ -316,3 +316,55 @@ void ath9k_cmn_debug_eeprom(struct dentr +@@ -315,3 +315,55 @@ void ath9k_cmn_debug_eeprom(struct dentr &fops_eeprom); } EXPORT_SYMBOL(ath9k_cmn_debug_eeprom); diff --git a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch index e09bbc08ea..c54dbbb188 100644 --- a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch @@ -1,8 +1,8 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1562,6 +1562,50 @@ static const struct file_operations fops - #endif - +@@ -1468,6 +1468,50 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); + } +static ssize_t read_file_diag(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) @@ -51,7 +51,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -@@ -1589,6 +1633,8 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -1491,6 +1535,8 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("gpio_led", S_IWUSR, sc->debug.debugfs_phy, sc, &fops_gpio_led); #endif diff --git a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch index 00451061f2..8b399f4b4c 100644 --- a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -55,7 +55,7 @@ ops->spectral_scan_config = ar9003_hw_spectral_scan_config; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -870,7 +870,8 @@ static void ath9k_init_txpower_limits(st +@@ -871,7 +871,8 @@ static void ath9k_init_txpower_limits(st if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); @@ -65,7 +65,7 @@ } static const struct ieee80211_iface_limit if_limits[] = { -@@ -1048,6 +1049,18 @@ static void ath9k_set_hw_capab(struct at +@@ -1049,6 +1050,18 @@ static void ath9k_set_hw_capab(struct at wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); } @@ -84,7 +84,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -1095,6 +1108,8 @@ int ath9k_init_device(u16 devid, struct +@@ -1096,6 +1109,8 @@ int ath9k_init_device(u16 devid, struct wiphy_read_of_freq_limits(hw->wiphy); diff --git a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch index 6d1820ecb7..752a4980a4 100644 --- a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch +++ b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch @@ -13,7 +13,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -803,6 +809,9 @@ static int ath9k_init_softc(u16 devid, s +@@ -804,6 +810,9 @@ static int ath9k_init_softc(u16 devid, s if (ret) goto err_hw; diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch deleted file mode 100644 index 22e26e7698..0000000000 --- a/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 4e32024cbb14230af3048e249e84f8c2b25ce45a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 Oct 2021 15:03:16 +0100 -Subject: [PATCH] brcmfmac: Read alternative firmware names from DT - -Add the ability to load the names of alternative firmwares from the -Device Tree node. This permits separate firmwares for 43436s and 43438 -and allows downstream firmwares to coexist with upstream. - -Signed-off-by: Phil Elwell ---- - .../wireless/broadcom/brcm80211/brcmfmac/of.c | 36 ++++++++++++++ - .../wireless/broadcom/brcm80211/brcmfmac/of.h | 7 +++ - .../broadcom/brcm80211/brcmfmac/sdio.c | 47 +++++++++++++++++-- - 3 files changed, 87 insertions(+), 3 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c -@@ -11,6 +11,7 @@ - #include "debug.h" - #include "core.h" - #include "common.h" -+#include "firmware.h" - #include "of.h" - - static int brcmf_of_get_country_codes(struct device *dev, -@@ -175,3 +176,38 @@ void brcmf_of_probe(struct device *dev, - sdio->oob_irq_nr = irq; - sdio->oob_irq_flags = irqf; - } -+ -+struct brcmf_firmware_mapping * -+brcmf_of_fwnames(struct device *dev, u32 *fwname_count) -+{ -+ struct device_node *np = dev->of_node; -+ struct brcmf_firmware_mapping *fwnames; -+ struct device_node *map_np, *fw_np; -+ int of_count; -+ int count = 0; -+ -+ map_np = of_get_child_by_name(np, "firmwares"); -+ of_count = of_get_child_count(map_np); -+ if (!of_count) -+ return NULL; -+ -+ fwnames = devm_kcalloc(dev, of_count, -+ sizeof(struct brcmf_firmware_mapping), -+ GFP_KERNEL); -+ -+ for_each_child_of_node(map_np, fw_np) -+ { -+ struct brcmf_firmware_mapping *cur = &fwnames[count]; -+ -+ if (of_property_read_u32(fw_np, "chipid", &cur->chipid) || -+ of_property_read_u32(fw_np, "revmask", &cur->revmask)) -+ continue; -+ cur->fw_base = of_get_property(fw_np, "fw_base", NULL); -+ if (cur->fw_base) -+ count++; -+ } -+ -+ *fwname_count = count; -+ -+ return count ? fwnames : NULL; -+} ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h -@@ -5,9 +5,20 @@ - #ifdef CONFIG_OF - void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, - struct brcmf_mp_device *settings); -+#ifdef CPTCFG_BRCMFMAC_SDIO -+struct brcmf_firmware_mapping * -+brcmf_of_fwnames(struct device *dev, u32 *map_count); -+#endif - #else - static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, - struct brcmf_mp_device *settings) - { - } -+#ifdef CPTCFG_BRCMFMAC_SDIO -+static struct brcmf_firmware_mapping * -+brcmf_of_fwnames(struct device *dev, u32 *map_count) -+{ -+ return NULL; -+} -+#endif - #endif /* CONFIG_OF */ ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -35,6 +35,7 @@ - #include "core.h" - #include "common.h" - #include "bcdc.h" -+#include "of.h" - - #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) - #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) -@@ -632,7 +633,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "b - /* per-board firmware binaries */ - MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin"); - --static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { -+static const struct brcmf_firmware_mapping sdio_fwnames[] = { - BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), - BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0), - BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4), -@@ -660,6 +661,9 @@ static const struct brcmf_firmware_mappi - BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752) - }; - -+static const struct brcmf_firmware_mapping *brcmf_sdio_fwnames = sdio_fwnames; -+static u32 brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); -+ - #define TXCTL_CREDITS 2 - - static void pkt_align(struct sk_buff *p, int len, int align) -@@ -4201,6 +4205,9 @@ static const struct brcmf_bus_ops brcmf_ - #define BRCMF_SDIO_FW_NVRAM 1 - #define BRCMF_SDIO_FW_CLM 2 - -+static struct brcmf_fw_request * -+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus); -+ - static void brcmf_sdio_firmware_callback(struct device *dev, int err, - struct brcmf_fw_request *fwreq) - { -@@ -4216,6 +4223,22 @@ static void brcmf_sdio_firmware_callback - - brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); - -+ if (err && brcmf_sdio_fwnames != sdio_fwnames) { -+ /* Try again with the standard firmware names */ -+ brcmf_sdio_fwnames = sdio_fwnames; -+ brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); -+ kfree(fwreq); -+ fwreq = brcmf_sdio_prepare_fw_request(bus); -+ if (!fwreq) { -+ err = -ENOMEM; -+ goto fail; -+ } -+ err = brcmf_fw_get_firmwares(dev, fwreq, -+ brcmf_sdio_firmware_callback); -+ if (!err) -+ return; -+ } -+ - if (err) - goto fail; - -@@ -4426,7 +4449,7 @@ brcmf_sdio_prepare_fw_request(struct brc - - fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev, - brcmf_sdio_fwnames, -- ARRAY_SIZE(brcmf_sdio_fwnames), -+ brcmf_sdio_fwnames_count, - fwnames, ARRAY_SIZE(fwnames)); - if (!fwreq) - return NULL; -@@ -4446,6 +4469,9 @@ struct brcmf_sdio *brcmf_sdio_probe(stru - struct brcmf_sdio *bus; - struct workqueue_struct *wq; - struct brcmf_fw_request *fwreq; -+ struct brcmf_firmware_mapping *of_fwnames, *fwnames = NULL; -+ const int fwname_size = sizeof(struct brcmf_firmware_mapping); -+ u32 of_fw_count; - - brcmf_dbg(TRACE, "Enter\n"); - -@@ -4528,6 +4554,21 @@ struct brcmf_sdio *brcmf_sdio_probe(stru - - brcmf_dbg(INFO, "completed!!\n"); - -+ of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fw_count); -+ if (of_fwnames) -+ fwnames = devm_kcalloc(sdiodev->dev, -+ of_fw_count + brcmf_sdio_fwnames_count, -+ fwname_size, GFP_KERNEL); -+ -+ if (fwnames) { -+ /* The array is scanned in order, so overrides come first */ -+ memcpy(fwnames, of_fwnames, of_fw_count * fwname_size); -+ memcpy(fwnames + of_fw_count, sdio_fwnames, -+ brcmf_sdio_fwnames_count * fwname_size); -+ brcmf_sdio_fwnames = fwnames; -+ brcmf_sdio_fwnames_count += of_fw_count; -+ } -+ - fwreq = brcmf_sdio_prepare_fw_request(bus); - if (!fwreq) { - ret = -ENOMEM; diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch new file mode 100644 index 0000000000..e4d9270ce8 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch @@ -0,0 +1,22 @@ +brcmfmac: disable dump_survey on Raspberry Pi + +Enabling this causes slow iwinfo calls on Raspberry Pi and LuCI slows down +when wireless is enabled. +https://github.com/openwrt/openwrt/issues/14013 + +Signed-off-by: Álvaro Fernández Rojas +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -8361,8 +8361,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802 + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) + ops->set_rekey_data = brcmf_cfg80211_set_rekey_data; + #endif ++#if !defined(CONFIG_ARCH_BCM2835) + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DUMP_OBSS)) + ops->dump_survey = brcmf_cfg80211_dump_survey; ++#endif /* CONFIG_ARCH_BCM2835 */ + + err = wiphy_register(wiphy); + if (err < 0) { diff --git a/package/kernel/mac80211/patches/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch b/package/kernel/mac80211/patches/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch new file mode 100644 index 0000000000..191eb67e8e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch @@ -0,0 +1,34 @@ +From: Felix Fietkau +Date: Wed, 3 Jan 2024 15:10:18 +0100 +Subject: [PATCH] wifi: mac80211: fix race condition on enabling fast-xmit + +fast-xmit must only be enabled after the sta has been uploaded to the driver, +otherwise it could end up passing the not-yet-uploaded sta via drv_tx calls +to the driver, leading to potential crashes because of uninitialized drv_priv +data. +Add a missing sta->uploaded check and re-check fast xmit after inserting a sta. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -911,6 +911,7 @@ static int sta_info_insert_finish(struct + + if (ieee80211_vif_is_mesh(&sdata->vif)) + mesh_accept_plinks_update(sdata); ++ ieee80211_check_fast_xmit(sta); + + return 0; + out_remove: +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3033,7 +3033,7 @@ void ieee80211_check_fast_xmit(struct st + sdata->vif.type == NL80211_IFTYPE_STATION) + goto out; + +- if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) ++ if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED) || !sta->uploaded) + goto out; + + if (test_sta_flag(sta, WLAN_STA_PS_STA) || diff --git a/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch new file mode 100644 index 0000000000..4bbd786043 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch @@ -0,0 +1,34 @@ +From: David Bauer +Date: Thu, 30 Nov 2023 07:32:52 +0100 +Subject: [PATCH] mac80211: avoid crashing on invalid band info + +Frequent crashes have been observed on MT7916 based platforms. While the +root of these crashes are currently unknown, they happen when decoding +rate information of connected STAs in AP mode. The rate-information is +associated with a band which is not available on the PHY. + +Check for this condition in order to avoid crashing the whole system. +This patch should be removed once the roout cause has been found and +fixed. + +Link: https://github.com/freifunk-gluon/gluon/issues/2980 + +Signed-off-by: David Bauer +--- + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2423,6 +2423,13 @@ static void sta_stats_decode_rate(struct + + sband = local->hw.wiphy->bands[band]; + ++ if (!sband) { ++ wiphy_warn(local->hw.wiphy, ++ "Invalid band %d\n", ++ band); ++ break; ++ } ++ + if (WARN_ON_ONCE(!sband->bitrates)) + break; + diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 65f6ca1e8e..1fea3bd0e9 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2023-12-18 -PKG_SOURCE_VERSION:=bebd9cffc2aeb2cecb40aadbb8c6eab3bdf7971b -PKG_MIRROR_HASH:=580261755bc3f251b8bc5f7f610274693c067432187570694d2f2ccab0edb62b +PKG_SOURCE_DATE:=2024-01-18 +PKG_SOURCE_VERSION:=f77188160441d5f77f08dd517632ae3f60c653b0 +PKG_MIRROR_HASH:=133a5e44624fe1933c893ee0b8ac75a847753f3490c26518c2ed9798f9ef53e0 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 diff --git a/package/libs/gettext-full/Makefile b/package/libs/gettext-full/Makefile index 1ed0e82df0..eb5b6d31bd 100644 --- a/package/libs/gettext-full/Makefile +++ b/package/libs/gettext-full/Makefile @@ -25,6 +25,8 @@ PKG_INSTALL:=1 PKG_BUILD_DEPENDS:=gettext-full/host libunistring libxml2 PKG_BUILD_PARALLEL:=0 +PKG_FIXUP:=autoreconf + HOST_BUILD_DEPENDS:=gperf/host libunistring/host libxml2/host HOST_BUILD_PARALLEL:=0 diff --git a/package/libs/libnl/Makefile b/package/libs/libnl/Makefile index 56f2c2825d..93817e5f40 100644 --- a/package/libs/libnl/Makefile +++ b/package/libs/libnl/Makefile @@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libnl -PKG_VERSION:=3.8.0 +PKG_VERSION:=3.9.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/thom311/libnl/releases/download/libnl$(subst .,_,$(PKG_VERSION)) -PKG_HASH:=bb726c6d7a08b121978d73ff98425bf313fa26a27a331d465e4f1d7ec5b838c6 +PKG_HASH:=aed507004d728a5cf11eab48ca4bf9e6e1874444e33939b9d3dfed25018ee9bb PKG_LICENSE:=LGPL-2.1 PKG_LICENSE_FILES:=COPYING diff --git a/package/libs/libtraceevent/Makefile b/package/libs/libtraceevent/Makefile index bcba7eaf43..54e8652192 100644 --- a/package/libs/libtraceevent/Makefile +++ b/package/libs/libtraceevent/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libtraceevent -PKG_VERSION:=1.7.3 +PKG_VERSION:=1.8.2 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/snapshot/ -PKG_HASH:=097b72e0d907f3107825fb2edf0188324bf70dc9da360f6efa68dc484ffde541 +PKG_HASH:=919f0c024c7b5059eace52d854d4df00ae7e361a4033e1b4d6fe01d97064a1b9 PKG_MAINTAINER:=Nick Hainke diff --git a/package/libs/libtracefs/Makefile b/package/libs/libtracefs/Makefile index eb879ee66d..0496f5983e 100644 --- a/package/libs/libtracefs/Makefile +++ b/package/libs/libtracefs/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libtracefs -PKG_VERSION:=1.7.0 +PKG_VERSION:=1.8.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/snapshot/ -PKG_HASH:=411fcbf3434ecbaefa6c2b1bf092266293a672e2d7ee46fdd6b402753cb8bd16 +PKG_HASH:=f92475d5c4cb509983697fb359ee615bef4f08ed8bdc9c690f6118ba68886de0 PKG_MAINTAINER:=Nick Hainke diff --git a/package/libs/libubox/Makefile b/package/libs/libubox/Makefile index 549e604679..a987304ba1 100644 --- a/package/libs/libubox/Makefile +++ b/package/libs/libubox/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/libubox.git -PKG_MIRROR_HASH:=daf411244a7f87c09c383c6fb69636a038c85f351bba93e80cc9aa530301199e -PKG_SOURCE_DATE:=2023-12-04.1 -PKG_SOURCE_VERSION:=ca3f6d0cdb1e588283c42d039779ceab303ceef2 +PKG_MIRROR_HASH:=071139fed757bea240d4ba8f55a0ff5a81862d23e16b39fc871ae07da78ae6a4 +PKG_SOURCE_DATE:=2024-01-26 +PKG_SOURCE_VERSION:=c1be505732e6d254464973bdeacb955214c76c46 PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE)) CMAKE_INSTALL:=1 @@ -105,6 +105,14 @@ CMAKE_HOST_OPTIONS += \ -DCMAKE_MACOSX_RPATH=1 \ -DCMAKE_INSTALL_RPATH="${STAGING_DIR_HOST}/lib" \ +ifeq ($(HOST_OS),Darwin) + define Host/Install + $(Host/Install/Default) + $(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/lib + cd "$(STAGING_DIR_HOSTPKG)/lib" && ln -sf ../../host/lib/libubox.* . + endef +endif + $(eval $(call BuildPackage,libubox)) $(eval $(call BuildPackage,libblobmsg-json)) $(eval $(call BuildPackage,jshn)) diff --git a/package/libs/libxml2/Makefile b/package/libs/libxml2/Makefile index d65085c9c1..030f7e45e8 100644 --- a/package/libs/libxml2/Makefile +++ b/package/libs/libxml2/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libxml2 -PKG_VERSION:=2.12.1 +PKG_VERSION:=2.12.4 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNOME/libxml2/$(basename $(PKG_VERSION)) -PKG_HASH:=8982b9ccdf7f456e30d8f7012d50858c6623e495333b6191def455c7e95427eb +PKG_HASH:=497360e423cf0bd99eacdb7c6215dea92e6d6e89ee940393c2bae0e77cb9b7d0 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=COPYING diff --git a/package/libs/mpfr/Makefile b/package/libs/mpfr/Makefile new file mode 100644 index 0000000000..39d6a035ab --- /dev/null +++ b/package/libs/mpfr/Makefile @@ -0,0 +1,64 @@ +# +# Copyright (C) 2023 Jeffery To +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mpfr +PKG_VERSION:=4.2.1 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=@GNU/mpfr http://www.mpfr.org/mpfr-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_HASH:=277807353a6726978996945af13e52829e3abd7a9a5b7fb2793894e18f1fcbb2 + +PKG_LICENSE:=LGPL-3.0-or-later +PKG_LICENSE_FILES:=COPYING.LESSER +PKG_MAINTAINER:=Jeffery To +PKG_CPE_ID:=cpe:/a:mpfr:gnu_mpfr + +PKG_BUILD_PARALLEL:=1 +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/libmpfr + SECTION:=libs + CATEGORY:=Libraries + TITLE:=GNU MPFR library + URL:=https://www.mpfr.org/ + DEPENDS:=+libgmp + ABI_VERSION:=6 +endef + +define Package/libmpfr/description +MPFR is a portable library written in C for arbitrary precision +arithmetic on floating-point numbers. It is based on the GNU MP library. +It aims to provide a class of floating-point numbers with precise +semantics. +endef + +CONFIGURE_ARGS += \ + --enable-thread-safe + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/mpf* $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmpfr.{a,so*} $(1)/usr/lib/ + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mpfr.pc $(1)/usr/lib/pkgconfig/ +endef + +define Package/libmpfr/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmpfr.so.* $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,libmpfr)) diff --git a/package/libs/mpfr/patches/001-only-src.patch b/package/libs/mpfr/patches/001-only-src.patch new file mode 100644 index 0000000000..bd9e38aefb --- /dev/null +++ b/package/libs/mpfr/patches/001-only-src.patch @@ -0,0 +1,22 @@ +--- a/Makefile.am ++++ b/Makefile.am +@@ -38,7 +38,7 @@ AUTOMAKE_OPTIONS = gnu + # old Automake version. + ACLOCAL_AMFLAGS = -I m4 + +-SUBDIRS = doc src tests tune tools/bench ++SUBDIRS = src + + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = mpfr.pc +--- a/Makefile.in ++++ b/Makefile.in +@@ -401,7 +401,7 @@ AUTOMAKE_OPTIONS = gnu + # libtoolize and in case some developer needs to switch back to an + # old Automake version. + ACLOCAL_AMFLAGS = -I m4 +-SUBDIRS = doc src tests tune tools/bench ++SUBDIRS = src + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = mpfr.pc + nobase_dist_doc_DATA = AUTHORS BUGS COPYING COPYING.LESSER NEWS TODO \ diff --git a/package/libs/wolfssl/Makefile b/package/libs/wolfssl/Makefile index 6451dca68d..8477fb85c5 100644 --- a/package/libs/wolfssl/Makefile +++ b/package/libs/wolfssl/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wolfssl -PKG_VERSION:=5.6.4-stable +PKG_VERSION:=5.6.6-stable PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/wolfSSL/wolfssl/archive/v$(PKG_VERSION) -PKG_HASH:=031691906794ff45e1e792561cf31759f5d29ac74936bc8dffb8b14f16d820b4 +PKG_HASH:=3d2ca672d41c2c2fa667885a80d6fa03c3e91f0f4f72f87aef2bc947e8c87237 PKG_FIXUP:=libtool libtool-abiver PKG_INSTALL:=1 diff --git a/package/libs/wolfssl/patches/100-disable-hardening-check.patch b/package/libs/wolfssl/patches/100-disable-hardening-check.patch index 368ec3e7e0..019645d796 100644 --- a/package/libs/wolfssl/patches/100-disable-hardening-check.patch +++ b/package/libs/wolfssl/patches/100-disable-hardening-check.patch @@ -1,6 +1,6 @@ --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h -@@ -2630,7 +2630,7 @@ extern void uITRON4_free(void *p) ; +@@ -2774,7 +2774,7 @@ extern void uITRON4_free(void *p) ; /* warning for not using harden build options (default with ./configure) */ /* do not warn if big integer support is disabled */ diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index 790bcfec63..558463e8ea 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2023-12-19 -PKG_SOURCE_VERSION:=a2d32f0dcf16880226680d07b07b249f77a3af58 -PKG_MIRROR_HASH:=765f51335ffa0a143421efbe129d484a90d7c4a0f3e08cb7840cc85408f3e60c +PKG_SOURCE_DATE:=2024-01-04 +PKG_SOURCE_VERSION:=f01345ec13b9b27ffd314d8689fb2d3f9c81a47d +PKG_MIRROR_HASH:=58e92e9ce1a2c8ccb487e95dadf806f38b38abbe7cb3cde61ff880de5eb85c2f PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 271c1f7bec..1a664abbf2 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -43,7 +43,7 @@ hostapd_append_wpa_key_mgmt() { case "$auth_type" in psk|eap) append wpa_key_mgmt "WPA-$auth_type_l" - [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}" + [ "${wpa:-2}" -ge 2 ] && [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}" [ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-${auth_type_l}-SHA256" ;; eap192) @@ -897,10 +897,21 @@ hostapd_set_bss_options() { } fi + json_get_vars ieee80211r + set_default ieee80211r 0 if [ "$wpa" -ge "1" ]; then - json_get_vars ieee80211r - set_default ieee80211r 0 + if [ "$fils" -gt 0 ]; then + json_get_vars fils_realm + set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)" + fi + append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N" + + hostapd_append_wpa_key_mgmt + [ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N" + fi + + if [ "$wpa" -ge "2" ]; then if [ "$ieee80211r" -gt "0" ]; then json_get_vars mobility_domain ft_psk_generate_local ft_over_ds reassociation_deadline @@ -909,7 +920,7 @@ hostapd_set_bss_options() { set_default reassociation_deadline 1000 case "$auth_type" in - psk|sae|psk-sae) + psk) set_default ft_psk_generate_local 1 ;; *) @@ -932,6 +943,10 @@ hostapd_set_bss_options() { set_default pmk_r1_push 0 [ -n "$r0kh" -a -n "$r1kh" ] || { + if [ -z "$auth_secret" -a -z "$key" ]; then + wireless_setup_vif_failed FT_KEY_CANT_BE_DERIVED + return 1 + fi ft_key=`echo -n "$mobility_domain/${auth_secret:-${key}}" | md5sum | awk '{print $1}'` set_default r0kh "ff:ff:ff:ff:ff:ff,*,$ft_key" @@ -950,18 +965,7 @@ hostapd_set_bss_options() { done fi fi - if [ "$fils" -gt 0 ]; then - json_get_vars fils_realm - set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)" - fi - append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N" - - hostapd_append_wpa_key_mgmt - [ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N" - fi - - if [ "$wpa" -ge "2" ]; then if [ -n "$network_bridge" -a "$rsn_preauth" = 1 ]; then set_default auth_cache 1 append bss_conf "rsn_preauth=1" "$N" @@ -1592,7 +1596,3 @@ EOF fi return 0 } - -hostapd_common_cleanup() { - killall meshd-nl80211 -} diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc index b85f523b35..dfddf8185b 100644 --- a/package/network/services/hostapd/files/hostapd.uc +++ b/package/network/services/hostapd/files/hostapd.uc @@ -2,9 +2,10 @@ let libubus = require("ubus"); import { open, readfile } from "fs"; import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common"; -let ubus = libubus.connect(); +let ubus = libubus.connect(null, 60); hostapd.data.config = {}; +hostapd.data.pending_config = {}; hostapd.data.file_fields = { vlan_file: true, @@ -127,12 +128,114 @@ function iface_update_supplicant_macaddr(phy, config) let macaddr_list = []; for (let i = 0; i < length(config.bss); i++) push(macaddr_list, config.bss[i].bssid); - ubus.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); + ubus.defer("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); +} + +function __iface_pending_next(pending, state, ret, data) +{ + let config = pending.config; + let phydev = pending.phydev; + let phy = pending.phy; + let bss = config.bss[0]; + + if (pending.defer) + pending.defer.abort(); + delete pending.defer; + switch (state) { + case "init": + let macaddr_list = []; + for (let i = 0; i < length(config.bss); i++) + push(macaddr_list, config.bss[i].bssid); + pending.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); + return "create_bss"; + case "create_bss": + let err = wdev_create(phy, bss.ifname, { mode: "ap" }); + if (err) { + hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); + return null; + } + + pending.call("wpa_supplicant", "phy_status", { phy: phy }); + return "check_phy"; + case "check_phy": + let phy_status = data; + if (phy_status && phy_status.state == "COMPLETED") { + if (iface_add(phy, config, phy_status)) + return "done"; + + hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`); + } + pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true }); + return "wpas_stopped"; + case "wpas_stopped": + if (!iface_add(phy, config)) + hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); + pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false }); + return null; + case "done": + default: + delete hostapd.data.pending_config[phy]; + break; + } +} + +function iface_pending_next(ret, data) +{ + let pending = true; + let cfg = this; + + while (pending) { + this.next_state = __iface_pending_next(cfg, this.next_state, ret, data); + if (!this.next_state) { + __iface_pending_next(cfg, "done"); + return; + } + pending = !this.defer; + } +} + +function iface_pending_abort() +{ + this.next_state = "done"; + this.next(); +} + +function iface_pending_ubus_call(obj, method, arg) +{ + let ubus = hostapd.data.ubus; + let pending = this; + this.defer = ubus.defer(obj, method, arg, (ret, data) => { delete pending.defer; pending.next(ret, data) }); +} + +const iface_pending_proto = { + next: iface_pending_next, + call: iface_pending_ubus_call, + abort: iface_pending_abort, +}; + +function iface_pending_init(phydev, config) +{ + let phy = phydev.name; + + let pending = proto({ + next_state: "init", + phydev: phydev, + phy: phy, + config: config, + next: iface_pending_next, + }, iface_pending_proto); + + hostapd.data.pending_config[phy] = pending; + pending.next(); } function iface_restart(phydev, config, old_config) { let phy = phydev.name; + let pending = hostapd.data.pending_config[phy]; + + if (pending) + pending.abort(); hostapd.remove_iface(phy); iface_remove(old_config); @@ -150,26 +253,7 @@ function iface_restart(phydev, config, old_config) bss.bssid = phydev.macaddr_next(); } - iface_update_supplicant_macaddr(phy, config); - - let bss = config.bss[0]; - let err = wdev_create(phy, bss.ifname, { mode: "ap" }); - if (err) - hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); - - let ubus = hostapd.data.ubus; - let phy_status = ubus.call("wpa_supplicant", "phy_status", { phy: phy }); - if (phy_status && phy_status.state == "COMPLETED") { - if (iface_add(phy, config, phy_status)) - return; - - hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`); - } - - ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true }); - if (!iface_add(phy, config)) - hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); - ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false }); + iface_pending_init(phydev, config); } function array_to_obj(arr, key, start) @@ -274,6 +358,9 @@ function iface_reload_config(phydev, config, old_config) if (is_equal(old_config.bss, config.bss)) return true; + if (hostapd.data.pending_config[phy]) + return false; + if (!old_config.bss || !old_config.bss[0]) return false; diff --git a/package/network/services/hostapd/patches/993-2023-10-28-ACS-Fix-typo-in-bw_40-frequency-array.patch b/package/network/services/hostapd/patches/993-2023-10-28-ACS-Fix-typo-in-bw_40-frequency-array.patch new file mode 100644 index 0000000000..948c51b196 --- /dev/null +++ b/package/network/services/hostapd/patches/993-2023-10-28-ACS-Fix-typo-in-bw_40-frequency-array.patch @@ -0,0 +1,25 @@ +From 7a733993211ad46cf3032038c1e7e6bdc2322336 Mon Sep 17 00:00:00 2001 +From: Michael-CY Lee +Date: Tue, 5 Sep 2023 09:43:25 +0800 +Subject: [PATCH] ACS: Fix typo in bw_40 frequency array + +The range for the 5 GHz channel 118 was encoded with an incorrect +channel number. + +Fixes: ed8e13decc71 (ACS: Extract bw40/80/160 freqs out of acs_usable_bwXXX_chan()) +Signed-off-by: Michael Lee +--- + src/ap/acs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/src/ap/acs.c ++++ b/src/ap/acs.c +@@ -256,7 +256,7 @@ struct bw_item { + static const struct bw_item bw_40[] = { + { 5180, 5200, 38 }, { 5220, 5240, 46 }, { 5260, 5280, 54 }, + { 5300, 5320, 62 }, { 5500, 5520, 102 }, { 5540, 5560, 110 }, +- { 5580, 5600, 110 }, { 5620, 5640, 126}, { 5660, 5680, 134 }, ++ { 5580, 5600, 118 }, { 5620, 5640, 126 }, { 5660, 5680, 134 }, + { 5700, 5720, 142 }, { 5745, 5765, 151 }, { 5785, 5805, 159 }, + { 5825, 5845, 167 }, { 5865, 5885, 175 }, + { 5955, 5975, 3 }, { 5995, 6015, 11 }, { 6035, 6055, 19 }, diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 6ff2257c32..66eba99901 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -1907,6 +1907,9 @@ void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequen struct hostapd_data *hapd; int i; + if (!ctx) + return; + blob_buf_init(&b, 0); blobmsg_add_u16(&b, "frequency", frequency); blobmsg_add_u16(&b, "width", chan_width); diff --git a/package/network/services/uhttpd/Makefile b/package/network/services/uhttpd/Makefile index 02a02405fd..37117bf911 100644 --- a/package/network/services/uhttpd/Makefile +++ b/package/network/services/uhttpd/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uhttpd -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git @@ -107,6 +107,13 @@ define Package/uhttpd-mod-ubus/install $(INSTALL_DATA) ./files/ubus.default $(1)/etc/uci-defaults/00_uhttpd_ubus endef +define Package/uhttpd-mod-ubus/postinst +#!/bin/sh +if [ -z "$${IPKG_INSTROOT}" ]; then + /etc/init.d/uhttpd reload +fi +endef + define Package/uhttpd-mod-ucode/install $(INSTALL_DIR) $(1)/usr/lib $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_ucode.so $(1)/usr/lib/ diff --git a/package/network/services/uhttpd/files/ubus.default b/package/network/services/uhttpd/files/ubus.default index 474016c1c5..d0a218a0ad 100644 --- a/package/network/services/uhttpd/files/ubus.default +++ b/package/network/services/uhttpd/files/ubus.default @@ -1,17 +1,11 @@ #!/bin/sh -commit=0 - if [ -z "$(uci -q get uhttpd.main.ubus_prefix)" ]; then uci set uhttpd.main.ubus_prefix=/ubus - commit=1 fi [ "$(uci -q get uhttpd.main.ubus_socket)" = "/var/run/ubus.sock" ] && { uci set uhttpd.main.ubus_socket='/var/run/ubus/ubus.sock' - commit=1 } -[ "$commit" = 1 ] && uci commit uhttpd && /etc/init.d/uhttpd reload - exit 0 diff --git a/package/network/utils/iproute2/Makefile b/package/network/utils/iproute2/Makefile index c21b78916b..2f9d2f2bc9 100644 --- a/package/network/utils/iproute2/Makefile +++ b/package/network/utils/iproute2/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iproute2 -PKG_VERSION:=6.6.0 +PKG_VERSION:=6.7.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 -PKG_HASH:=8738c804afd09f0bf756937f0c3de23117832a98d8cbbf50386cf5005cd613ce +PKG_HASH:=ff942dd9828d7d1f867f61fe72ce433078c31e5d8e4a78e20f02cb5892e8841d PKG_BUILD_PARALLEL:=1 PKG_BUILD_DEPENDS:=iptables PKG_LICENSE:=GPL-2.0 diff --git a/package/network/utils/iproute2/patches/100-configure.patch b/package/network/utils/iproute2/patches/100-configure.patch deleted file mode 100644 index 2d4fb7b9b3..0000000000 --- a/package/network/utils/iproute2/patches/100-configure.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/configure -+++ b/configure -@@ -36,7 +36,8 @@ int main(int argc, char **argv) { - } - EOF - -- if $CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1; then -+# OpenWrt: disable ATM support even if present on host system -+ if [ 1 -eq 0 ]; then - echo "TC_CONFIG_ATM:=y" >>$CONFIG - echo yes - else diff --git a/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch b/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch index ba6ca4c9b2..8c70c14489 100644 --- a/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch +++ b/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch @@ -1,6 +1,6 @@ --- a/Makefile +++ b/Makefile -@@ -67,9 +67,9 @@ WFLAGS += -Wmissing-declarations -Wold-s +@@ -68,9 +68,9 @@ WFLAGS += -Wmissing-declarations -Wold-s CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS) YACCFLAGS = -d -t -v diff --git a/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch b/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch index a8cdd103ba..0d22875751 100644 --- a/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch +++ b/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -411,7 +411,7 @@ check_tirpc() +@@ -391,7 +391,7 @@ check_tirpc() check_mnl() { diff --git a/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch b/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch index 0c5c3f59ed..bffacddb21 100644 --- a/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch +++ b/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -266,7 +266,7 @@ EOF +@@ -246,7 +246,7 @@ EOF check_elf() { diff --git a/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch b/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch index 4cce2c3ca6..570e9c7038 100644 --- a/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch +++ b/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -469,7 +469,7 @@ EOF +@@ -449,7 +449,7 @@ EOF check_cap() { diff --git a/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch b/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch index 28ba7e5217..4d7fb76308 100644 --- a/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch +++ b/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -398,7 +398,7 @@ check_selinux() +@@ -378,7 +378,7 @@ check_selinux() check_tirpc() { diff --git a/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch b/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch index c7fceb2e22..765e4ad2e8 100644 --- a/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch +++ b/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -290,7 +290,7 @@ int main(int argc, char **argv) { +@@ -270,7 +270,7 @@ int main(int argc, char **argv) { } EOF @@ -9,7 +9,7 @@ local ret=$? rm -f $TMPDIR/libbpf_test.c $TMPDIR/libbpf_test -@@ -308,7 +308,7 @@ int main(int argc, char **argv) { +@@ -288,7 +288,7 @@ int main(int argc, char **argv) { } EOF diff --git a/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch b/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch index d1948860e8..92bf5cb66d 100644 --- a/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch +++ b/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch @@ -1,12 +1,12 @@ --- a/configure +++ b/configure -@@ -455,14 +455,8 @@ EOF +@@ -435,14 +435,8 @@ EOF if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then echo "no" else - if ${PKG_CONFIG} libbsd --exists; then -- echo 'CFLAGS += -DHAVE_LIBBSD' `${PKG_CONFIG} libbsd --cflags` >>$CONFIG -- echo 'LDLIBS +=' `${PKG_CONFIG} libbsd --libs` >> $CONFIG +- echo 'CFLAGS += -DHAVE_LIBBSD' "$(${PKG_CONFIG} libbsd --cflags)" >>$CONFIG +- echo 'LDLIBS +=' "$(${PKG_CONFIG} libbsd --libs)" >> $CONFIG - echo "no" - else - echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG diff --git a/package/network/utils/iproute2/patches/300-selinux-configurable.patch b/package/network/utils/iproute2/patches/300-selinux-configurable.patch index 817abf7d17..a611ba75f0 100644 --- a/package/network/utils/iproute2/patches/300-selinux-configurable.patch +++ b/package/network/utils/iproute2/patches/300-selinux-configurable.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -385,7 +385,7 @@ check_libbpf() +@@ -365,7 +365,7 @@ check_libbpf() check_selinux() # SELinux is a compile time option in the ss utility { diff --git a/package/network/utils/iwinfo/Makefile b/package/network/utils/iwinfo/Makefile index c6a14956fd..4fef2babbb 100644 --- a/package/network/utils/iwinfo/Makefile +++ b/package/network/utils/iwinfo/Makefile @@ -11,9 +11,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/iwinfo.git -PKG_SOURCE_DATE:=2023-07-01 -PKG_SOURCE_VERSION:=ca79f64154b107f192ec3c1ba631816cb8b07922 -PKG_MIRROR_HASH:=5eddf584a1c3ed5637162d6bfc573ed1ce3691fcb38bdd55bf9f1e11e82ccc46 +PKG_SOURCE_DATE:=2023-11-19 +PKG_SOURCE_VERSION:=a34977c0760c93480491c8eb94da656b57d7f4cc +PKG_MIRROR_HASH:=cb01671a2a9155f8ba55751ab1fe28488c5821212dd97ba5b79653640abb787e PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=GPL-2.0 diff --git a/package/network/utils/uqmi/Makefile b/package/network/utils/uqmi/Makefile index 26b588c7ef..6753e47cdb 100644 --- a/package/network/utils/uqmi/Makefile +++ b/package/network/utils/uqmi/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git -PKG_SOURCE_DATE:=2023-10-29 -PKG_SOURCE_VERSION:=eea292401c388a4eb59c0caf5d00aa046c6059f4 -PKG_MIRROR_HASH:=744f7e2010bd16ca08b03551287a0e1d119e1e6e099f8abf935328d3d1344893 +PKG_SOURCE_DATE:=2024-01-16 +PKG_SOURCE_VERSION:=c3488b831ce6285c8107704156b9b8ed7d59deb3 +PKG_MIRROR_HASH:=3ca47f2ae22bc1adcb05560e6dbea824063fa914670c13f107e7e78f33399779 PKG_MAINTAINER:=Matti Laakso PKG_LICENSE:=GPL-2.0 diff --git a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh index f8e655455a..49fd87ff9d 100755 --- a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh +++ b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh @@ -85,8 +85,8 @@ proto_qmi_setup() { echo "Waiting for SIM initialization" local uninitialized_timeout=0 # timeout 3s for first call to avoid hanging uqmi - uqmi -d "$device" --get-pin-status -t 3000 > /dev/null 2>&1 - while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do + uqmi -d "$device" -t 3000 --get-pin-status > /dev/null 2>&1 + while uqmi -s -d "$device" -t 1000 --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do [ -e "$device" ] || return 1 if [ "$uninitialized_timeout" -lt "$timeout" -o "$timeout" = "0" ]; then let uninitialized_timeout++ @@ -102,7 +102,7 @@ proto_qmi_setup() { # Check if UIM application is stuck in illegal state local uim_state_timeout=0 while true; do - json_load "$(uqmi -s -d "$device" --uim-get-sim-state)" + json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)" json_get_var card_application_state card_application_state # SIM card is either completely absent or state is labeled as illegal @@ -111,9 +111,9 @@ proto_qmi_setup() { echo "SIM in illegal state - Power-cycling SIM" # Try to reset SIM application - uqmi -d "$device" --uim-power-off --uim-slot 1 + uqmi -d "$device" -t 1000 --uim-power-off --uim-slot 1 sleep 3 - uqmi -d "$device" --uim-power-on --uim-slot 1 + uqmi -d "$device" -t 1000 --uim-power-on --uim-slot 1 if [ "$uim_state_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then let uim_state_timeout++ @@ -130,10 +130,10 @@ proto_qmi_setup() { fi done - if uqmi -s -d "$device" --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' && - uqmi -s -d "$device" --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then + if uqmi -s -d "$device" -t 1000 --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' && + uqmi -s -d "$device" -t 1000 --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then [ -n "$pincode" ] && { - uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null || { + uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null || { echo "Unable to verify PIN" proto_notify_error "$interface" PIN_FAILED proto_block_restart "$interface" @@ -141,10 +141,10 @@ proto_qmi_setup() { } } else - json_load "$(uqmi -s -d "$device" --get-pin-status)" + json_load "$(uqmi -s -d "$device" -t 1000 --get-pin-status)" json_get_var pin1_status pin1_status if [ -z "$pin1_status" ]; then - json_load "$(uqmi -s -d "$device" --uim-get-sim-state)" + json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)" json_get_var pin1_status pin1_status fi json_get_var pin1_verify_tries pin1_verify_tries @@ -167,7 +167,7 @@ proto_qmi_setup() { return 1 } if [ -n "$pincode" ]; then - uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || { + uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || { echo "Unable to verify PIN" proto_notify_error "$interface" PIN_FAILED proto_block_restart "$interface" @@ -194,7 +194,7 @@ proto_qmi_setup() { fi if [ -n "$plmn" ]; then - json_load "$(uqmi -s -d "$device" --get-plmn)" + json_load "$(uqmi -s -d "$device" -t 1000 --get-plmn)" json_get_var plmn_mode mode json_get_vars mcc mnc || { mcc=0 @@ -218,16 +218,16 @@ proto_qmi_setup() { fi # Cleanup current state if any - uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 - uqmi -s -d "$device" --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 # Go online - uqmi -s -d "$device" --set-device-operating-mode online > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-device-operating-mode online > /dev/null 2>&1 # Set IP format - uqmi -s -d "$device" --set-data-format 802.3 > /dev/null 2>&1 - uqmi -s -d "$device" --wda-set-data-format 802.3 > /dev/null 2>&1 - dataformat="$(uqmi -s -d "$device" --wda-get-data-format)" + uqmi -s -d "$device" -t 1000 --set-data-format 802.3 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --wda-set-data-format 802.3 > /dev/null 2>&1 + dataformat="$(uqmi -s -d "$device" -t 1000 --wda-get-data-format)" if [ "$dataformat" = '"raw-ip"' ]; then @@ -240,13 +240,13 @@ proto_qmi_setup() { echo "Y" > /sys/class/net/$ifname/qmi/raw_ip fi - uqmi -s -d "$device" --sync > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --sync > /dev/null 2>&1 - uqmi -s -d "$device" --network-register > /dev/null 2>&1 + uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1 # PLMN selection must happen after the call to network-register if [ -n "$mcc" -a -n "$mnc" ]; then - uqmi -s -d "$device" --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || { + uqmi -s -d "$device" -t 1000 --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || { echo "Unable to set PLMN" proto_notify_error "$interface" PLMN_FAILED proto_block_restart "$interface" @@ -255,10 +255,10 @@ proto_qmi_setup() { fi [ -n "$modes" ] && { - uqmi -s -d "$device" --set-network-modes "$modes" > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-network-modes "$modes" > /dev/null 2>&1 sleep 3 # Scan network to not rely on registration-timeout after RAT change - uqmi -s -d "$device" --network-scan > /dev/null 2>&1 + uqmi -s -d "$device" -t 30000 --network-scan > /dev/null 2>&1 } echo "Waiting for network registration" @@ -266,7 +266,7 @@ proto_qmi_setup() { local registration_timeout=0 local registration_state="" while true; do - registration_state=$(uqmi -s -d "$device" --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null) + registration_state=$(uqmi -s -d "$device" -t 1000 --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null) [ "$registration_state" = "registered" ] && break @@ -274,7 +274,7 @@ proto_qmi_setup() { if [ "$registration_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then [ "$registration_state" = "searching" ] || { echo "Device stopped network registration. Restart network registration" - uqmi -s -d "$device" --network-register > /dev/null 2>&1 + uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1 } let registration_timeout++ sleep 1 @@ -302,7 +302,7 @@ proto_qmi_setup() { # establish a non-LTE data session. profile_pdptype="$pdptype" [ "$profile_pdptype" = "ip" ] && profile_pdptype="ipv4" - uqmi -s -d "$device" --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1 if [ "$pdptype" = "ip" ]; then [ -z "$autoconnect" ] && autoconnect=1 @@ -312,16 +312,16 @@ proto_qmi_setup() { fi [ "$pdptype" = "ip" -o "$pdptype" = "ipv4v6" ] && { - cid_4=$(uqmi -s -d "$device" --get-client-id wds) + cid_4=$(uqmi -s -d "$device" -t 1000 --get-client-id wds) if ! [ "$cid_4" -eq "$cid_4" ] 2> /dev/null; then echo "Unable to obtain client ID" proto_notify_error "$interface" NO_CID return 1 fi - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1 - pdh_4=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" \ + pdh_4=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_4" \ --start-network \ ${apn:+--apn $apn} \ ${profile:+--profile $profile} \ @@ -333,35 +333,35 @@ proto_qmi_setup() { # pdh_4 is a numeric value on success if ! [ "$pdh_4" -eq "$pdh_4" ] 2> /dev/null; then echo "Unable to connect IPv4" - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 fi # Check data connection state - connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" --get-data-status) + connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --get-data-status) [ "$connstat" == '"connected"' ] || { echo "No data link!" - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 } } [ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && { - cid_6=$(uqmi -s -d "$device" --get-client-id wds) + cid_6=$(uqmi -s -d "$device" -t 1000 --get-client-id wds) if ! [ "$cid_6" -eq "$cid_6" ] 2> /dev/null; then echo "Unable to obtain client ID" proto_notify_error "$interface" NO_CID return 1 fi - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1 : "${v6apn:=${apn}}" : "${v6profile:=${profile}}" - pdh_6=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" \ + pdh_6=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_6" \ --start-network \ ${v6apn:+--apn $v6apn} \ ${v6profile:+--profile $v6profile} \ @@ -373,16 +373,16 @@ proto_qmi_setup() { # pdh_6 is a numeric value on success if ! [ "$pdh_6" -eq "$pdh_6" ] 2> /dev/null; then echo "Unable to connect IPv6" - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 fi # Check data connection state - connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status) + connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status) [ "$connstat" == '"connected"' ] || { echo "No data link!" - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 } @@ -407,7 +407,7 @@ proto_qmi_setup() { [ -n "$pdh_6" ] && { if [ -z "$dhcpv6" -o "$dhcpv6" = 0 ]; then - json_load "$(uqmi -s -d $device --set-client-id wds,$cid_6 --get-current-settings)" + json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_6 --get-current-settings)" json_select ipv6 json_get_var ip_6 ip json_get_var gateway_6 gateway @@ -449,7 +449,7 @@ proto_qmi_setup() { [ -n "$pdh_4" ] && { if [ "$dhcp" = 0 ]; then - json_load "$(uqmi -s -d $device --set-client-id wds,$cid_4 --get-current-settings)" + json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_4 --get-current-settings)" json_select ipv4 json_get_var ip_4 ip json_get_var gateway_4 gateway @@ -492,16 +492,16 @@ qmi_wds_stop() { [ -n "$cid" ] || return - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --stop-network 0xffffffff \ --autoconnect > /dev/null 2>&1 [ -n "$pdh" ] && { - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --stop-network "$pdh" > /dev/null 2>&1 } - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --release-client-id wds > /dev/null 2>&1 } diff --git a/package/network/utils/wireguard-tools/Makefile b/package/network/utils/wireguard-tools/Makefile index 5b1fab057d..e2a86c97d8 100644 --- a/package/network/utils/wireguard-tools/Makefile +++ b/package/network/utils/wireguard-tools/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wireguard-tools PKG_VERSION:=1.0.20210914 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=wireguard-tools-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-tools/snapshot/ diff --git a/package/network/utils/wireguard-tools/files/wireguard_watchdog b/package/network/utils/wireguard-tools/files/wireguard_watchdog index 0126f699bb..fc90f4a25b 100644 --- a/package/network/utils/wireguard-tools/files/wireguard_watchdog +++ b/package/network/utils/wireguard-tools/files/wireguard_watchdog @@ -59,7 +59,7 @@ check_peer_activity() { } # query ubus for all active wireguard interfaces -wg_ifaces=$(ubus -S call network.interface dump | jsonfilter -e '@.interface[@.up=true]' | jsonfilter -a -e '@[@.proto="wireguard"].interface' | tr "\n" " ") +eval $(ubus -S call network.interface dump | jsonfilter -e 'wg_ifaces=@.interface[@.up=true && @.proto="wireguard"].interface') # check every peer in every active wireguard interface config_load network diff --git a/package/system/fstools/Makefile b/package/system/fstools/Makefile index 7e3779e61e..717e59f836 100644 --- a/package/system/fstools/Makefile +++ b/package/system/fstools/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git -PKG_MIRROR_HASH:=e9953b038a2c2ed2c4783b66d1c0d0cea0deab2f2bfa6712929243e3197c3bdd -PKG_SOURCE_DATE:=2023-05-28 -PKG_SOURCE_VERSION:=3a07943e1e60699ba952e605f0cf23c82de356cb +PKG_MIRROR_HASH:=32e39891455b602e9deb367c9ce2d099dc72353fad0bf0433307416925f7b393 +PKG_SOURCE_DATE:=2024-01-22 +PKG_SOURCE_VERSION:=08cd7083cac4bddf88459efa0881ee52858e7d0a CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 diff --git a/package/system/mtd/src/Makefile b/package/system/mtd/src/Makefile index e204ecb221..a1277a6739 100644 --- a/package/system/mtd/src/Makefile +++ b/package/system/mtd/src/Makefile @@ -20,6 +20,7 @@ obj.mvebu = linksys_bootcount.o obj.kirkwood = linksys_bootcount.o obj.ipq806x = linksys_bootcount.o obj.ipq40xx = linksys_bootcount.o +obj.qualcommax = linksys_bootcount.o ifdef FIS_SUPPORT obj += fis.o diff --git a/package/system/ubox/Makefile b/package/system/ubox/Makefile index ed55617cfa..e74ae00b3f 100644 --- a/package/system/ubox/Makefile +++ b/package/system/ubox/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubox.git -PKG_SOURCE_DATE:=2023-11-30 -PKG_SOURCE_VERSION:=c08709cceb554cba02c935d1442f6a042fe6b2a8 -PKG_MIRROR_HASH:=719ae701546df7c5972352d778a980cbc9f48623dda86443398698837124818b +PKG_SOURCE_DATE:=2024-01-24 +PKG_SOURCE_VERSION:=2c5887cb46883a28d69071c4349c3dabbbe3972c +PKG_MIRROR_HASH:=0ded95382fd3a2e9751ea5fdd16c2afb7dcc52499f6ab47951c5db9525a4faa9 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 diff --git a/package/utils/bcm27xx-userland/Makefile b/package/utils/bcm27xx-userland/Makefile index 9d7f6dd822..461cf3e954 100644 --- a/package/utils/bcm27xx-userland/Makefile +++ b/package/utils/bcm27xx-userland/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-userland -PKG_VERSION:=c4fd1b8986c6d6d4ae5cd51e65a8bbeb495dfa4e +PKG_VERSION:=96a7334ae9d5fc9db7ac92e59852377df63f1848 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/userland/tar.gz/$(PKG_VERSION)? -PKG_HASH:=ab8a5b27c34cf1b97de87b895448a6355229f73b679866b47c51a723273cc8ae +PKG_HASH:=557ee8390de5db1ed90386c1ba0221e7f6f9dd87e858a00a34be3b1f9ede193f PKG_FLAGS:=nonshared @@ -41,7 +41,6 @@ define Package/bcm27xx-userland CATEGORY:=Utilities DEPENDS:=@TARGET_bcm27xx TITLE:=BCM27xx userland tools - DEFAULT:=y if TARGET_bcm27xx endef define Package/bcm27xx-userland/description diff --git a/package/utils/bcm27xx-utils/Makefile b/package/utils/bcm27xx-utils/Makefile new file mode 100644 index 0000000000..ec41b70c30 --- /dev/null +++ b/package/utils/bcm27xx-utils/Makefile @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk + +PKG_NAME:=bcm27xx-utils +PKG_VERSION:=2024-01-18 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/raspberrypi/utils.git +PKG_SOURCE_VERSION:=e65f5ec102e74218cda7da9fdc8b1caa0fd1127d +PKG_MIRROR_HASH:=14f4aa1a8115240d702251bc399b53cbfa0928813f70a73ca27b22da94b696d2 + +PKG_FLAGS:=nonshared +PKG_BUILD_FLAGS:=no-lto + +PKG_LICENSE:=BSD-3-Clause +PKG_LICENSE_FILES:=LICENCE + +CMAKE_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/bcm27xx-utils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=@TARGET_bcm27xx +libfdt + TITLE:=BCM27xx scripts and simple applications + PROVIDES:=bcm27xx-userland +endef + +define Package/bcm27xx-utils/description + BCM27xx scripts and simple applications. + Replaces bcm27xx-userland scripts and applications. +endef + +define Package/bcm27xx-utils/install + $(INSTALL_DIR) $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtmerge $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtoverlay $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtparam $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepdump $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepflash.sh $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepmake $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/otpset $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/overlaycheck $(1)/usr/bin + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/bin/overlaycheck_exclusions.txt $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ovmerge $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/pinctrl $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/raspinfo $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vcgencmd $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vclog $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vcmailbox $(1)/usr/bin +endef + +$(eval $(call BuildPackage,bcm27xx-utils)) diff --git a/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch b/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch new file mode 100644 index 0000000000..9dd6d99626 --- /dev/null +++ b/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch @@ -0,0 +1,255 @@ +From 0db3fb3119eda8c2360454c2a01f84602a879c38 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Tue, 16 Jan 2024 15:32:12 +0100 +Subject: [PATCH] raspinfo: adapt to OpenWrt +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + raspinfo/raspinfo | 186 ++++------------------------------------------ + 1 file changed, 13 insertions(+), 173 deletions(-) + +--- a/raspinfo/raspinfo ++++ b/raspinfo/raspinfo +@@ -1,4 +1,4 @@ +-#!/bin/bash ++#!/bin/sh + + # Some of the regex's used in sed + # Catch basic IP6 address "s/\([0-9a-fA-F]\{1,4\}:\)\{7,7\}[0-9a-fA-F]\{1,4\}/y.y.y.y.y.y.y.y/g" +@@ -6,147 +6,6 @@ + # IP4 d.d.d.d decimal "s/\([0-9]\{1,3\}\.\)\{3,3\}[0-9]\{1,3\}/x.x.x.x/g" + # mac address "s/\([0-9a-fA-F]\{2,2\}\:\)\{5,5\}[0-9a-fA-F]\{2,2\}/m.m.m.m/g" + +- +-display_info_drm() { +- # If running X then can use xrandr, otherwise +- # dump the /sys/class entries for the displays +- if command -v xrandr > /dev/null && +- DISPLAY=${DISPLAY:-:0} xrandr --listmonitors &>/dev/null; +- then +- echo "Running (F)KMS and X" +- echo +- +- DISPLAY=${DISPLAY:-:0} xrandr --verbose +- else +- echo "Running (F)KMS, console" +- echo +- +- for card in /sys/class/drm/card[0-9]-*; +- do +- echo $card +- +- # if kmsprint isn't installed print basic mode info +- if ! command -v kmsprint > /dev/null; then +- if [ -f $card/modes ]; +- then +- cat $card/modes +- else +- echo "No modes found" +- fi +- fi +- +- if [ -f $card/edid ]; +- then +- base64 $card/edid +- else +- echo "No EDID found" +- fi +- echo +- done +- fi +- +- # kmsprint is more useful, but not always installed +- echo +- if command -v kmsprint > /dev/null; then +- kmsprint +- echo +- kmsprint -m +- else +- echo "kmsprint is not installed. Install with: sudo apt install kms++-utils" +- fi +- +- echo +- +- # dump the /sys/class entries for the displays +- cardfound=0 +- for card in `seq 0 9`; +- do +- if sudo test -f "/sys/kernel/debug/dri/${card}/state"; +- then +- for hdmi in 0 1; +- do +- if sudo test -f "/sys/kernel/debug/dri/${card}/hdmi${hdmi}_regs"; +- then +- echo "HDMI${hdmi}: $(sudo cat /sys/kernel/debug/dri/$card/hdmi${hdmi}_regs | grep HOTPLUG)" +- fi +- done +- echo +- echo "/sys/kernel/debug/dri/$card/state:" +- sudo cat "/sys/kernel/debug/dri/$card/state" +- echo +- cardfound=1 +- fi +- done +- if [ "$cardfound" == "0" ]; +- then +- echo "kms state not found" +- fi +- echo +- +-} +- +-display_info_legacy() { +- # Legacy mode +- echo "Running Legacy framebuffer" +- echo +- +- for card in `seq 0 9`; +- do +- F="/dev/fb${card}" +- if test -e $F; +- then +- echo Framebuffer: $F +- fbset -s -fb $F +- fi +- done +- +- disps=`tvservice -l | awk '/Display Number/{print substr($3,1,1)}'` +- +- tmp=$(mktemp) +- +- for display in $disps +- do +- echo +- echo "Display: " $display +- +- tvservice -v $display -s +- tvservice -v $display -n +- tvservice -v $display -m CEA +- tvservice -v $display -m DMT +- +- echo +- tvservice -v $display -d $tmp > /dev/null +- base64 $tmp +- done +- +- rm $tmp +-} +- +-display_info() { +- # Check if we are running a KMS/DRM system +- +- if [ -d "/dev/dri" ]; +- then +- display_info_drm +- else +- display_info_legacy +- fi +-} +- +-audio_info() { +- aplay -l +- echo +- aplay -L +- echo +- systemctl --user status pipewire.socket pipewire.service pulseaudio.service pulseaudio.socket +- echo +- if command -v pactl > /dev/null; then +- pactl info +- else +- echo pactl not installed +- fi +-} +- + OUT=raspinfo.txt + + rm -f $OUT +@@ -163,8 +22,6 @@ echo + cat /etc/os-release | head -4 + echo + +-cat /etc/rpi-issue +-echo + uname -a + + cat /proc/cpuinfo | tail -3 +@@ -190,17 +47,6 @@ echo + cat /proc/swaps + + echo +-echo "Package version information" +-echo "---------------------------" +- +-apt-cache policy raspberrypi-ui-mods | head -2 +-apt-cache policy raspberrypi-sys-mods | head -2 +-apt-cache policy openbox | head -2 +-apt-cache policy lxpanel | head -2 +-apt-cache policy pcmanfm | head -2 +-apt-cache policy rpd-plym-splash | head -2 +- +-echo + echo "Networking Information" + echo "----------------------" + echo +@@ -212,21 +58,11 @@ echo "USB Information" + echo "---------------" + echo + +-lsusb -t +- +-echo +-echo "Display Information" +-echo "-------------------" +-echo +- +-display_info +- +-echo +-echo "Audio Information" +-echo "-------------------" +-echo +- +-audio_info ++if command -v lsusb > /dev/null; then ++ lsusb -t ++else ++ echo usbutils not installed ++fi + + echo + echo "config.txt" +@@ -250,7 +86,7 @@ echo "-----------------" + echo + + if command -v pinctrl > /dev/null; then +- sudo pinctrl 2>&1 ++ pinctrl 2>&1 + elif command -v raspi-gpio > /dev/null; then + raspi-gpio get 2>&1 + else +@@ -263,9 +99,9 @@ echo "------------------" + echo + + if command -v vcdbg > /dev/null; then +- sudo vcdbg log msg 2>&1 ++ vcdbg log msg 2>&1 + elif command -v vclog > /dev/null; then +- sudo vclog --msg 2>&1 ++ vclog --msg 2>&1 + else + echo "vcdbg not found" + fi +@@ -284,5 +120,9 @@ echo + echo "EEPROM" + echo "------" + echo +-sudo rpi-eeprom-update ++if command -v rpi-eeprom-update > /dev/null; then ++ rpi-eeprom-update ++else ++ echo bcm27xx-eeprom not installed ++fi + fi diff --git a/package/utils/busybox/Config-defaults.in b/package/utils/busybox/Config-defaults.in index b3c3f9a0b2..515bea3d1d 100644 --- a/package/utils/busybox/Config-defaults.in +++ b/package/utils/busybox/Config-defaults.in @@ -1333,7 +1333,7 @@ config BUSYBOX_DEFAULT_USE_BB_CRYPT default n config BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA bool - default n + default y config BUSYBOX_DEFAULT_ADD_SHELL bool default n @@ -1366,7 +1366,7 @@ config BUSYBOX_DEFAULT_CHPASSWD default n config BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO string - default "md5" + default "sha256" config BUSYBOX_DEFAULT_CRYPTPW bool default n diff --git a/package/utils/jsonfilter/Makefile b/package/utils/jsonfilter/Makefile index 56f96d52b5..fda66bbfb4 100644 --- a/package/utils/jsonfilter/Makefile +++ b/package/utils/jsonfilter/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/jsonpath.git -PKG_SOURCE_DATE:=2018-02-04 -PKG_SOURCE_VERSION:=c7e938d6582a436dddc938539e72dd1320625c54 -PKG_MIRROR_HASH:=0601b4d7aa5ee096e99388a57cb0701673ab58fccd6ed2984a2abbd4f846e045 +PKG_SOURCE_DATE:=2024-01-23 +PKG_SOURCE_VERSION:=594cfa86469c005972ba750614f5b3f1af84d0f6 +PKG_MIRROR_HASH:=70d2e0870b746920af4569631218c38c1dddfee4f5d029ec8ea0a67999bdafcd CMAKE_INSTALL:=1 PKG_MAINTAINER:=Jo-Philipp Wich diff --git a/scripts/ipkg-build b/scripts/ipkg-build index 122cca2cb4..6abcc58832 100755 --- a/scripts/ipkg-build +++ b/scripts/ipkg-build @@ -181,7 +181,7 @@ for file_mode in $file_modes; do done $TAR -X "$tmp_dir"/tarX --format=gnu --numeric-owner --sort=name -cpf - --mtime="$TIMESTAMP" . | gzip -n - > "$tmp_dir"/data.tar.gz -installed_size=$(stat -c "%s" "$tmp_dir"/data.tar.gz) +installed_size=$(zcat < "$tmp_dir"/data.tar.gz | wc -c) sed -i -e "s/^Installed-Size: .*/Installed-Size: $installed_size/" \ "$pkg_dir"/$CONTROL/control diff --git a/scripts/json_overview_image_info.py b/scripts/json_overview_image_info.py index 89b7d4fe20..0d2cf7f1ef 100755 --- a/scripts/json_overview_image_info.py +++ b/scripts/json_overview_image_info.py @@ -55,9 +55,9 @@ if output: "target/linux/", "val.DEFAULT_PACKAGES", "val.ARCH_PACKAGES", + "V=s", ], stdout=PIPE, - stderr=PIPE, check=True, env=environ.copy().update({"TOPDIR": Path().cwd()}), universal_newlines=True, diff --git a/scripts/metadata.pm b/scripts/metadata.pm index 587ce7207d..ecfe42c0bc 100644 --- a/scripts/metadata.pm +++ b/scripts/metadata.pm @@ -257,6 +257,7 @@ sub parse_package_metadata($) { /^License: \s*(.+)\s*$/ and $pkg->{license} = $1; /^LicenseFiles: \s*(.+)\s*$/ and $pkg->{licensefiles} = $1; /^CPE-ID: \s*(.+)\s*$/ and $pkg->{cpe_id} = $1; + /^URL: \s*(.+)\s*$/ and $pkg->{url} = $1; /^ABI-Version: \s*(.+)\s*$/ and $pkg->{abi_version} = $1; /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; /^Provides: \s*(.+)\s*$/ and do { @@ -344,6 +345,7 @@ sub parse_package_manifest_metadata($) { /^Section:\s*(.+)\s*$/ and $pkg->{section} = $1; /^SourceDateEpoch: \s*(.+)\s*$/ and $pkg->{sourcedateepoch} = $1; /^CPE-ID:\s*(.+)\s*$/ and $pkg->{cpe_id} = $1; + /^URL:\s*(.+)\s*$/ and $pkg->{url} = $1; /^Architecture:\s*(.+)\s*$/ and $pkg->{architecture} = $1; /^Installed-Size:\s*(.+)\s*$/ and $pkg->{installedsize} = $1; /^Filename:\s*(.+)\s*$/ and $pkg->{filename} = $1; diff --git a/scripts/rstrip.sh b/scripts/rstrip.sh index e47960a941..2aa7e96fda 100755 --- a/scripts/rstrip.sh +++ b/scripts/rstrip.sh @@ -20,7 +20,7 @@ TARGETS=$* exit 1 } -find $TARGETS -type f -a -exec file {} \; | \ +find $TARGETS -not -path \*/lib/firmware/\* -a -type f -a -exec file {} \; | \ sed -n -e 's/^\(.*\):.*ELF.*\(executable\|relocatable\|shared object\).*,.*/\1:\2/p' | \ ( IFS=":" diff --git a/target/imagebuilder/Makefile b/target/imagebuilder/Makefile index 3bbadc7204..c3b6c9c10c 100644 --- a/target/imagebuilder/Makefile +++ b/target/imagebuilder/Makefile @@ -27,7 +27,7 @@ all: compile $(BIN_DIR)/$(IB_NAME).tar.xz: clean rm -rf $(PKG_BUILD_DIR) mkdir -p $(IB_KDIR) $(IB_LDIR) $(PKG_BUILD_DIR)/staging_dir/host/lib \ - $(PKG_BUILD_DIR)/target $(PKG_BUILD_DIR)/scripts $(IB_DTSDIR) + $(PKG_BUILD_DIR)/target/linux $(PKG_BUILD_DIR)/scripts $(IB_DTSDIR) -cp $(TOPDIR)/.config $(PKG_BUILD_DIR)/.config $(SED) 's/^CONFIG_BINARY_FOLDER=.*/# CONFIG_BINARY_FOLDER is not set/' $(PKG_BUILD_DIR)/.config $(SED) 's/^CONFIG_DOWNLOAD_FOLDER=.*/# CONFIG_DOWNLOAD_FOLDER is not set/' $(PKG_BUILD_DIR)/.config @@ -78,7 +78,9 @@ ifneq ($(CONFIG_SIGNATURE_CHECK),) $(CP) -L $(STAGING_DIR_ROOT)/usr/sbin/opkg-key $(PKG_BUILD_DIR)/scripts/ endif - $(CP) -L $(TOPDIR)/target/linux $(PKG_BUILD_DIR)/target/ + $(CP) -L $(TOPDIR)/target/linux/Makefile $(PKG_BUILD_DIR)/target/linux + $(CP) -L $(TOPDIR)/target/linux/generic $(PKG_BUILD_DIR)/target/linux + $(CP) -L $(TOPDIR)/target/linux/$(BOARD) $(PKG_BUILD_DIR)/target/linux if [ -d $(TOPDIR)/staging_dir/host/lib/grub ]; then \ $(CP) $(TOPDIR)/staging_dir/host/lib/grub/ $(PKG_BUILD_DIR)/staging_dir/host/lib; \ fi diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch b/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch index 2c70b44f4b..ec72f91d0f 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch @@ -22,7 +22,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -3611,7 +3611,7 @@ static int dpaa2_eth_setup_dpni(struct f +@@ -3614,7 +3614,7 @@ static int dpaa2_eth_setup_dpni(struct f dev_err(dev, "DPNI version %u.%u not supported, need >= %u.%u\n", priv->dpni_ver_major, priv->dpni_ver_minor, DPNI_VER_MAJOR, DPNI_VER_MINOR); diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch b/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch index c47598749c..af5ff2aea6 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch @@ -21,7 +21,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -2080,10 +2080,8 @@ static int dpaa2_eth_open(struct net_dev +@@ -2083,10 +2083,8 @@ static int dpaa2_eth_open(struct net_dev goto enable_err; } @@ -33,7 +33,7 @@ Signed-off-by: Paolo Abeni return 0; -@@ -2157,7 +2155,6 @@ static int dpaa2_eth_stop(struct net_dev +@@ -2160,7 +2158,6 @@ static int dpaa2_eth_stop(struct net_dev int retries = 10; if (dpaa2_eth_is_type_phy(priv)) { diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch b/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch index 45f07decc9..c31a470182 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch @@ -49,7 +49,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -4441,9 +4441,8 @@ static int dpaa2_eth_connect_mac(struct +@@ -4444,9 +4444,8 @@ static int dpaa2_eth_connect_mac(struct err = dpaa2_mac_open(mac); if (err) goto err_free_mac; @@ -60,7 +60,7 @@ Signed-off-by: Paolo Abeni err = dpaa2_mac_connect(mac); if (err && err != -EPROBE_DEFER) netdev_err(priv->net_dev, "Error connecting to the MAC endpoint: %pe", -@@ -4452,11 +4451,12 @@ static int dpaa2_eth_connect_mac(struct +@@ -4455,11 +4454,12 @@ static int dpaa2_eth_connect_mac(struct goto err_close_mac; } @@ -74,7 +74,7 @@ Signed-off-by: Paolo Abeni err_free_mac: kfree(mac); return err; -@@ -4464,15 +4464,18 @@ err_free_mac: +@@ -4467,15 +4467,18 @@ err_free_mac: static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) { diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch b/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch index 7c394c55db..4e39e9a0ac 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch @@ -33,7 +33,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -4708,6 +4708,10 @@ static int dpaa2_eth_probe(struct fsl_mc +@@ -4711,6 +4711,10 @@ static int dpaa2_eth_probe(struct fsl_mc } #endif @@ -44,7 +44,7 @@ Signed-off-by: Paolo Abeni err = dpaa2_eth_setup_irqs(dpni_dev); if (err) { netdev_warn(net_dev, "Failed to set link interrupt, fall back to polling\n"); -@@ -4720,10 +4724,6 @@ static int dpaa2_eth_probe(struct fsl_mc +@@ -4723,10 +4727,6 @@ static int dpaa2_eth_probe(struct fsl_mc priv->do_link_poll = true; } @@ -55,7 +55,7 @@ Signed-off-by: Paolo Abeni err = dpaa2_eth_dl_alloc(priv); if (err) goto err_dl_register; -@@ -4759,13 +4759,13 @@ err_dl_port_add: +@@ -4762,13 +4762,13 @@ err_dl_port_add: err_dl_trap_register: dpaa2_eth_dl_free(priv); err_dl_register: @@ -71,7 +71,7 @@ Signed-off-by: Paolo Abeni dpaa2_eth_free_rings(priv); err_alloc_rings: err_csum: -@@ -4813,9 +4813,6 @@ static int dpaa2_eth_remove(struct fsl_m +@@ -4816,9 +4816,6 @@ static int dpaa2_eth_remove(struct fsl_m #endif unregister_netdev(net_dev); @@ -81,7 +81,7 @@ Signed-off-by: Paolo Abeni dpaa2_eth_dl_port_del(priv); dpaa2_eth_dl_traps_unregister(priv); -@@ -4826,6 +4823,9 @@ static int dpaa2_eth_remove(struct fsl_m +@@ -4829,6 +4826,9 @@ static int dpaa2_eth_remove(struct fsl_m else fsl_mc_free_irqs(ls_dev); diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch b/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch index 28ffe2288c..9b068ce8f5 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -2018,8 +2018,11 @@ static int dpaa2_eth_link_state_update(s +@@ -2021,8 +2021,11 @@ static int dpaa2_eth_link_state_update(s /* When we manage the MAC/PHY using phylink there is no need * to manually update the netif_carrier. @@ -54,7 +54,7 @@ Signed-off-by: Paolo Abeni goto out; /* Chech link state; speed / duplex changes are not treated yet */ -@@ -2058,6 +2061,8 @@ static int dpaa2_eth_open(struct net_dev +@@ -2061,6 +2064,8 @@ static int dpaa2_eth_open(struct net_dev priv->dpbp_dev->obj_desc.id, priv->bpid); } @@ -63,7 +63,7 @@ Signed-off-by: Paolo Abeni if (!dpaa2_eth_is_type_phy(priv)) { /* We'll only start the txqs when the link is actually ready; * make sure we don't race against the link up notification, -@@ -2076,6 +2081,7 @@ static int dpaa2_eth_open(struct net_dev +@@ -2079,6 +2084,7 @@ static int dpaa2_eth_open(struct net_dev err = dpni_enable(priv->mc_io, 0, priv->mc_token); if (err < 0) { @@ -71,7 +71,7 @@ Signed-off-by: Paolo Abeni netdev_err(net_dev, "dpni_enable() failed\n"); goto enable_err; } -@@ -2083,6 +2089,8 @@ static int dpaa2_eth_open(struct net_dev +@@ -2086,6 +2092,8 @@ static int dpaa2_eth_open(struct net_dev if (dpaa2_eth_is_type_phy(priv)) dpaa2_mac_start(priv->mac); @@ -80,7 +80,7 @@ Signed-off-by: Paolo Abeni return 0; enable_err: -@@ -2154,6 +2162,8 @@ static int dpaa2_eth_stop(struct net_dev +@@ -2157,6 +2165,8 @@ static int dpaa2_eth_stop(struct net_dev int dpni_enabled = 0; int retries = 10; @@ -89,7 +89,7 @@ Signed-off-by: Paolo Abeni if (dpaa2_eth_is_type_phy(priv)) { dpaa2_mac_stop(priv->mac); } else { -@@ -2161,6 +2171,8 @@ static int dpaa2_eth_stop(struct net_dev +@@ -2164,6 +2174,8 @@ static int dpaa2_eth_stop(struct net_dev netif_carrier_off(net_dev); } @@ -98,7 +98,7 @@ Signed-off-by: Paolo Abeni /* On dpni_disable(), the MC firmware will: * - stop MAC Rx and wait for all Rx frames to be enqueued to software * - cut off WRIOP dequeues from egress FQs and wait until transmission -@@ -2486,12 +2498,20 @@ static int dpaa2_eth_ts_ioctl(struct net +@@ -2489,12 +2501,20 @@ static int dpaa2_eth_ts_ioctl(struct net static int dpaa2_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct dpaa2_eth_priv *priv = netdev_priv(dev); @@ -121,7 +121,7 @@ Signed-off-by: Paolo Abeni return -EOPNOTSUPP; } -@@ -4451,7 +4471,9 @@ static int dpaa2_eth_connect_mac(struct +@@ -4454,7 +4474,9 @@ static int dpaa2_eth_connect_mac(struct goto err_close_mac; } @@ -131,7 +131,7 @@ Signed-off-by: Paolo Abeni return 0; -@@ -4464,9 +4486,12 @@ err_free_mac: +@@ -4467,9 +4489,12 @@ err_free_mac: static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) { @@ -145,7 +145,7 @@ Signed-off-by: Paolo Abeni if (!mac) return; -@@ -4485,6 +4510,7 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4488,6 +4513,7 @@ static irqreturn_t dpni_irq0_handler_thr struct fsl_mc_device *dpni_dev = to_fsl_mc_device(dev); struct net_device *net_dev = dev_get_drvdata(dev); struct dpaa2_eth_priv *priv = netdev_priv(net_dev); @@ -153,7 +153,7 @@ Signed-off-by: Paolo Abeni int err; err = dpni_get_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle, -@@ -4502,7 +4528,12 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4505,7 +4531,12 @@ static irqreturn_t dpni_irq0_handler_thr dpaa2_eth_update_tx_fqids(priv); rtnl_lock(); @@ -167,7 +167,7 @@ Signed-off-by: Paolo Abeni dpaa2_eth_disconnect_mac(priv); else dpaa2_eth_connect_mac(priv); -@@ -4603,6 +4634,8 @@ static int dpaa2_eth_probe(struct fsl_mc +@@ -4606,6 +4637,8 @@ static int dpaa2_eth_probe(struct fsl_mc priv = netdev_priv(net_dev); priv->net_dev = net_dev; @@ -305,7 +305,7 @@ Signed-off-by: Paolo Abeni if (pause->autoneg) return -EOPNOTSUPP; -@@ -309,8 +341,12 @@ static void dpaa2_eth_get_ethtool_stats( +@@ -307,8 +339,12 @@ static void dpaa2_eth_get_ethtool_stats( } *(data + i++) = buf_cnt; diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch b/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch index f72f9e3a43..521c9d4a54 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch @@ -34,7 +34,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -4527,7 +4527,6 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4530,7 +4530,6 @@ static irqreturn_t dpni_irq0_handler_thr dpaa2_eth_set_mac_addr(netdev_priv(net_dev)); dpaa2_eth_update_tx_fqids(priv); @@ -42,7 +42,7 @@ Signed-off-by: Paolo Abeni /* We can avoid locking because the "endpoint changed" IRQ * handler is the only one who changes priv->mac at runtime, * so we are not racing with anyone. -@@ -4537,7 +4536,6 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4540,7 +4539,6 @@ static irqreturn_t dpni_irq0_handler_thr dpaa2_eth_disconnect_mac(priv); else dpaa2_eth_connect_mac(priv); @@ -50,7 +50,7 @@ Signed-off-by: Paolo Abeni } return IRQ_HANDLED; -@@ -4856,9 +4854,7 @@ static int dpaa2_eth_remove(struct fsl_m +@@ -4859,9 +4857,7 @@ static int dpaa2_eth_remove(struct fsl_m else fsl_mc_free_irqs(ls_dev); diff --git a/target/linux/ath79/dts/ar7100.dtsi b/target/linux/ath79/dts/ar7100.dtsi index a03f282a0f..6648311619 100644 --- a/target/linux/ath79/dts/ar7100.dtsi +++ b/target/linux/ath79/dts/ar7100.dtsi @@ -113,7 +113,7 @@ #reset-cells = <1>; }; - pcie0: pcie-controller@17010000 { + pcie0: pcie@17010000 { compatible = "qca,ar7100-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/ar7161_aruba_ap-105.dts b/target/linux/ath79/dts/ar7161_aruba_ap-105.dts index c8510a8944..dd110fc185 100644 --- a/target/linux/ath79/dts/ar7161_aruba_ap-105.dts +++ b/target/linux/ath79/dts/ar7161_aruba_ap-105.dts @@ -94,7 +94,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 1>; nvmem-cell-names = "mac-address"; @@ -103,7 +103,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 2>; nvmem-cell-names = "mac-address"; diff --git a/target/linux/ath79/dts/ar7161_aruba_ap-175.dts b/target/linux/ath79/dts/ar7161_aruba_ap-175.dts index 96a76a3cfc..62a2083d20 100644 --- a/target/linux/ath79/dts/ar7161_aruba_ap-175.dts +++ b/target/linux/ath79/dts/ar7161_aruba_ap-175.dts @@ -120,7 +120,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 1>; nvmem-cell-names = "mac-address"; @@ -129,7 +129,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 2>; nvmem-cell-names = "mac-address"; diff --git a/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi b/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi index e3f48fee85..50c0748a38 100644 --- a/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi +++ b/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi @@ -196,7 +196,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; qca,no-eeprom; @@ -204,7 +204,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts b/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts index b62111c110..639736d9c4 100644 --- a/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts +++ b/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts @@ -136,7 +136,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; nvmem-cells = <&macaddr_lan 0>, <&cal_art_1000>; @@ -145,7 +145,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; nvmem-cells = <&macaddr_wan 1>, <&cal_art_5000>; diff --git a/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts b/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts index ddcf68970d..e0aa5704cd 100644 --- a/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts +++ b/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts @@ -95,7 +95,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; ieee80211-freq-limit = <2402000 2482000>; @@ -105,7 +105,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; ieee80211-freq-limit = <2402000 2482000 4900000 5990000>; diff --git a/target/linux/ath79/dts/ar7161_meraki_mr16.dts b/target/linux/ath79/dts/ar7161_meraki_mr16.dts index 6b8574e880..b732010446 100644 --- a/target/linux/ath79/dts/ar7161_meraki_mr16.dts +++ b/target/linux/ath79/dts/ar7161_meraki_mr16.dts @@ -70,7 +70,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; qca,no-eeprom; @@ -80,7 +80,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar7161_netgear_wndap360.dts b/target/linux/ath79/dts/ar7161_netgear_wndap360.dts index 9761234714..020b45d9e1 100644 --- a/target/linux/ath79/dts/ar7161_netgear_wndap360.dts +++ b/target/linux/ath79/dts/ar7161_netgear_wndap360.dts @@ -147,7 +147,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; nvmem-cells = <&macaddr_art_120c>, <&calibration_art_1000>; @@ -156,7 +156,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; nvmem-cells = <&macaddr_art_520c 1>, <&calibration_art_5000>; diff --git a/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi b/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi index 296ecc8c4e..d30b4dad30 100644 --- a/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi +++ b/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi @@ -126,7 +126,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; @@ -153,7 +153,7 @@ }; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; diff --git a/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi b/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi index 065068571c..54a15c49c1 100644 --- a/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi +++ b/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi @@ -131,7 +131,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; nvmem-cells = <&macaddr_bdata_60>; @@ -140,7 +140,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; nvmem-cells = <&macaddr_bdata_76>; diff --git a/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts b/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts index a770ca04a8..7508be1df1 100644 --- a/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts +++ b/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts @@ -92,13 +92,13 @@ &pcie0 { status = "okay"; - wifi@0,11 { + wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; qca,no-eeprom; }; - wifi@0,12 { + wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar7242_avm_fritz300e.dts b/target/linux/ath79/dts/ar7242_avm_fritz300e.dts index 310a2b1ee2..7a0d7dd268 100644 --- a/target/linux/ath79/dts/ar7242_avm_fritz300e.dts +++ b/target/linux/ath79/dts/ar7242_avm_fritz300e.dts @@ -85,7 +85,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; startup-delay-us = <300000>; enable-active-high; diff --git a/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts b/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts index 8e8deba933..861964fdfc 100644 --- a/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts +++ b/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts @@ -75,7 +75,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,002a"; reg = <0x0 0 0 0 0>; nvmem-cells = <&macaddr_art_0 1>; diff --git a/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts b/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts index 69629335b3..a7def14c73 100644 --- a/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts +++ b/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts @@ -75,7 +75,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,002a"; reg = <0x0 0 0 0 0>; nvmem-cells = <&macaddr_art_0 (-1)>; diff --git a/target/linux/ath79/dts/ar7242_meraki_mr12.dts b/target/linux/ath79/dts/ar7242_meraki_mr12.dts index adea2778ea..5218a5ce27 100644 --- a/target/linux/ath79/dts/ar7242_meraki_mr12.dts +++ b/target/linux/ath79/dts/ar7242_meraki_mr12.dts @@ -70,7 +70,7 @@ &pcie { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "pci168c,002a"; reg = <0x0000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar724x.dtsi b/target/linux/ath79/dts/ar724x.dtsi index c090eb5e0f..c758fc244e 100644 --- a/target/linux/ath79/dts/ar724x.dtsi +++ b/target/linux/ath79/dts/ar724x.dtsi @@ -121,7 +121,7 @@ #reset-cells = <1>; }; - pcie: pcie-controller@180c0000 { + pcie: pcie@180c0000 { compatible = "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts b/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts index 211c565c24..e4d2ff1e11 100644 --- a/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts +++ b/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts @@ -54,7 +54,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; gpio-export { diff --git a/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts b/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts index 3751374af6..b10f7fc965 100644 --- a/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts +++ b/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts @@ -52,7 +52,7 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; enable-active-high; - gpio = <&gpio 20 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 20 GPIO_ACTIVE_HIGH>; }; }; diff --git a/target/linux/ath79/dts/ar9331_onion_omega.dts b/target/linux/ath79/dts/ar9331_onion_omega.dts index 81fab872b5..5d9e96e048 100644 --- a/target/linux/ath79/dts/ar9331_onion_omega.dts +++ b/target/linux/ath79/dts/ar9331_onion_omega.dts @@ -43,7 +43,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts b/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts index 61cbb1aae2..63f394a4f9 100644 --- a/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts +++ b/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts @@ -41,7 +41,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts b/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts index 69965f86a8..ad987dbca1 100644 --- a/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts +++ b/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts @@ -101,7 +101,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 19 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 19 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts b/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts index 3597a0d1bb..20f412e918 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts @@ -8,5 +8,5 @@ }; ®_usb_vbus { - gpio = <&gpio 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts b/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts index 7a1a577ed7..7b307cd6d0 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts @@ -76,7 +76,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts b/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts index b07f9a7820..91023111a6 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts @@ -72,7 +72,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts b/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts index 0806bcc170..7fb87dab0f 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts @@ -8,5 +8,5 @@ }; ®_usb_vbus { - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi b/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi index 329822ad10..303cb566ab 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi +++ b/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi @@ -38,7 +38,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g-xhpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g-xhpnd.dts new file mode 100644 index 0000000000..5fa44b4412 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g-xhpnd.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ar9342_mikrotik_routerboard-911g.dtsi" + +#include +#include + +/ { + compatible = "mikrotik,routerboard-911g-xhpnd", "qca,ar9342"; + model = "MikroTik RouterBOARD 911G-(2,5)HPnD"; +}; diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g.dtsi b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g.dtsi new file mode 100644 index 0000000000..86b4bc358b --- /dev/null +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g.dtsi @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ar9344.dtsi" + +#include +#include + +/ { + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + gpio_key: gpio_key { + compatible = "mikrotik,gpio-rb91x-key"; + gpio-controller; + #gpio-cells = <2>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; + }; + + gpio_latch: gpio_latch { + compatible = "gpio-latch"; + gpio-controller; + #gpio-cells = <2>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, + <&gpio 1 GPIO_ACTIVE_HIGH>, + <&gpio 2 GPIO_ACTIVE_HIGH>, + <&gpio 3 GPIO_ACTIVE_HIGH>, + <0>, /* Not connected */ + <&gpio 13 GPIO_ACTIVE_HIGH>, + <&gpio 14 GPIO_ACTIVE_HIGH>, + <&gpio_key 0 GPIO_ACTIVE_HIGH>, + <&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ + }; + + nand_gpio { + compatible = "mikrotik,rb91x-nand"; + + gpios = <&gpio_latch 3 GPIO_ACTIVE_HIGH>, /* Read */ + <&gpio 4 GPIO_ACTIVE_HIGH>, /* Ready (RDY) */ + <&gpio_latch 5 GPIO_ACTIVE_LOW>, /* Chip Enable (nCE) */ + <&gpio_latch 6 GPIO_ACTIVE_HIGH>, /* Command Latch Enable (CLE) */ + <&gpio_latch 7 GPIO_ACTIVE_HIGH>, /* Address Latch Enable (ALE) */ + <&gpio 12 GPIO_ACTIVE_LOW>, /* Read/Write Enable (nRW) */ + <&gpio_latch 8 GPIO_ACTIVE_LOW>, /* Latch Enable (nLE) */ + <&gpio_key 2 GPIO_ACTIVE_HIGH>; /* Key poll disable */ + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "booter"; + reg = <0x0 0x0040000>; + read-only; + }; + + partition@40000 { + label = "kernel"; + reg = <0x0040000 0x03c0000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x0400000 0x7c00000>; + }; + }; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&gpio_key 1 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&gpio_latch 1 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + user { + label = "green:user"; + gpios = <&gpio_latch 2 GPIO_ACTIVE_HIGH>; + }; + + led1 { + label = "green:led1"; + gpios = <&ssr 0 GPIO_ACTIVE_HIGH>; + }; + + led2 { + label = "green:led2"; + gpios = <&ssr 1 GPIO_ACTIVE_HIGH>; + }; + + led3 { + label = "green:led3"; + gpios = <&ssr 2 GPIO_ACTIVE_HIGH>; + }; + + led4 { + label = "green:led4"; + gpios = <&ssr 3 GPIO_ACTIVE_HIGH>; + }; + + led5 { + label = "green:led5"; + gpios = <&ssr 4 GPIO_ACTIVE_HIGH>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + beeper { + gpio-export,name = "beeper"; + gpio-export,output = <1>; /* Must be 1 to avoid EMI induced clicking noise */ + gpios = <&ssr 5 GPIO_ACTIVE_HIGH>; + }; + + usb_power { + gpio-export,name = "power-usb"; + gpio-export,output = <1>; + gpios = <&ssr 6 GPIO_ACTIVE_HIGH>; + }; + + pcie_power { + gpio-export,name = "power-pcie"; + gpio-export,output = <0>; + gpios = <&ssr 7 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&ref { + clock-frequency = <40000000>; +}; + +&spi { + status = "okay"; + + compatible = "qca,ar7100-spi"; + + cs-gpios = <0>, <&gpio_latch 0 GPIO_ACTIVE_LOW>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "mikrotik,routerboot-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "routerboot"; + reg = <0x0 0x0>; + read-only; + }; + + hard_config { + read-only; + }; + + bios { + size = <0x1000>; + read-only; + }; + + soft_config { + }; + }; + }; + + ssr: ssr@1 { + compatible = "fairchild,74hc595"; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + reg = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&mdio0 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; + +ð0 { + status = "okay"; + + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + pll-data = <0x02000000 0x00000101 0x00001313>; + + gmac-config { + device = <&gmac>; + rgmii-gmac0 = <1>; + rxd-delay = <1>; + txd-delay = <1>; + }; +}; + +&wmac { + status = "okay"; + qca,no-eeprom; +}; diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts index f14e138026..81d7284b3d 100644 --- a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts @@ -1,229 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "ar9344.dtsi" +#include "ar9342_mikrotik_routerboard-911g.dtsi" #include #include / { compatible = "mikrotik,routerboard-912uag-2hpnd", "qca,ar9342"; - model = "MikroTik RouterBOARD 912UAG-2HPnD"; - - aliases { - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; - }; - - gpio_key: gpio_key { - compatible = "mikrotik,gpio-rb91x-key"; - gpio-controller; - #gpio-cells = <2>; - gpio = <&gpio 15 GPIO_ACTIVE_HIGH>; - }; - - gpio_latch: gpio_latch { - compatible = "gpio-latch"; - gpio-controller; - #gpio-cells = <2>; - gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, - <&gpio 1 GPIO_ACTIVE_HIGH>, - <&gpio 2 GPIO_ACTIVE_HIGH>, - <&gpio 3 GPIO_ACTIVE_HIGH>, - <0>, /* Not connected */ - <&gpio 13 GPIO_ACTIVE_HIGH>, - <&gpio 14 GPIO_ACTIVE_HIGH>, - <&gpio_key 0 GPIO_ACTIVE_HIGH>, - <&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ - }; - - nand_gpio { - compatible = "mikrotik,rb91x-nand"; - - gpios = <&gpio_latch 3 GPIO_ACTIVE_HIGH>, /* Read */ - <&gpio 4 GPIO_ACTIVE_HIGH>, /* Ready (RDY) */ - <&gpio_latch 5 GPIO_ACTIVE_LOW>, /* Chip Enable (nCE) */ - <&gpio_latch 6 GPIO_ACTIVE_HIGH>, /* Command Latch Enable (CLE) */ - <&gpio_latch 7 GPIO_ACTIVE_HIGH>, /* Address Latch Enable (ALE) */ - <&gpio 12 GPIO_ACTIVE_LOW>, /* Read/Write Enable (nRW) */ - <&gpio_latch 8 GPIO_ACTIVE_LOW>, /* Latch Enable (nLE) */ - <&gpio_key 2 GPIO_ACTIVE_HIGH>; /* Key poll disable */ - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "booter"; - reg = <0x0 0x0040000>; - read-only; - }; - - partition@40000 { - label = "kernel"; - reg = <0x0040000 0x03c0000>; - }; - - partition@400000 { - label = "ubi"; - reg = <0x0400000 0x7c00000>; - }; - }; - }; - - keys { - compatible = "gpio-keys-polled"; - poll-interval = <20>; - - button@0 { - label = "reset"; - linux,code = ; - gpios = <&gpio_key 1 GPIO_ACTIVE_LOW>; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_power: power { - label = "green:power"; - gpios = <&gpio_latch 1 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - - user { - label = "green:user"; - gpios = <&gpio_latch 2 GPIO_ACTIVE_HIGH>; - }; - - led1 { - label = "green:led1"; - gpios = <&ssr 0 GPIO_ACTIVE_HIGH>; - }; - - led2 { - label = "green:led2"; - gpios = <&ssr 1 GPIO_ACTIVE_HIGH>; - }; - - led3 { - label = "green:led3"; - gpios = <&ssr 2 GPIO_ACTIVE_HIGH>; - }; - - led4 { - label = "green:led4"; - gpios = <&ssr 3 GPIO_ACTIVE_HIGH>; - }; - - led5 { - label = "green:led5"; - gpios = <&ssr 4 GPIO_ACTIVE_HIGH>; - }; - }; - - gpio-export { - compatible = "gpio-export"; - - beeper { - gpio-export,name = "beeper"; - gpio-export,output = <1>; /* Must be 1 to avoid EMI induced clicking noise */ - gpios = <&ssr 5 GPIO_ACTIVE_HIGH>; - }; - - usb_power { - gpio-export,name = "power-usb"; - gpio-export,output = <1>; - gpios = <&ssr 6 GPIO_ACTIVE_HIGH>; - }; - - pcie_power { - gpio-export,name = "power-pcie"; - gpio-export,output = <0>; - gpios = <&ssr 7 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&ref { - clock-frequency = <40000000>; -}; - -&spi { - status = "okay"; - - compatible = "qca,ar7100-spi"; - - cs-gpios = <0>, <&gpio_latch 0 GPIO_ACTIVE_LOW>; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <50000000>; - - partitions { - compatible = "mikrotik,routerboot-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "routerboot"; - reg = <0x0 0x0>; - read-only; - }; - - hard_config { - read-only; - }; - - bios { - size = <0x1000>; - read-only; - }; - - soft_config { - }; - }; - }; - - ssr: ssr@1 { - compatible = "fairchild,74hc595"; - gpio-controller; - #gpio-cells = <2>; - registers-number = <1>; - reg = <1>; - spi-max-frequency = <50000000>; - }; -}; - -&mdio0 { - status = "okay"; - - phy0: ethernet-phy@0 { - reg = <0>; - }; -}; - -ð0 { - status = "okay"; - - phy-mode = "rgmii-id"; - phy-handle = <&phy0>; - pll-data = <0x02000000 0x00000101 0x00001313>; - - gmac-config { - device = <&gmac>; - rgmii-gmac0 = <1>; - rxd-delay = <1>; - txd-delay = <1>; - }; -}; - -&wmac { - status = "okay"; - qca,no-eeprom; + model = "MikroTik RouterBOARD 912UAG-(2,5)HPnD"; }; &pcie { diff --git a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts index c448ac4e61..ee73428625 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,bullet-m-xw", "ubnt,xw", "qca,ar9342"; @@ -11,15 +11,15 @@ status = "okay"; phy4: ethernet-phy@4 { - phy-mode = "rgmii"; reg = <4>; + max-speed = <100>; }; }; ð0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-txid"; phy-handle = <&phy4>; gmac-config { diff --git a/target/linux/ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts new file mode 100644 index 0000000000..bc01bdffb5 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "ar9342_ubnt_xw.dtsi" + +#include +#include +#include + +/ { + compatible = "ubnt,litebeam-m5-xw", "qca,ar9342"; + model = "Ubiquiti LiteBeam M5 (XW)"; + + aliases { + led-boot = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + led-failsafe = &led_status; + label-mac-device = &wmac; + }; + + leds { + compatible = "gpio-leds"; + + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + led-wlan { + color = ; + function = LED_FUNCTION_WLAN; + linux,default-trigger = "phy0tpt"; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + + led_status: led-power { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&mdio0 { + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + phy-mode = "mii"; + reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + }; +}; + +ð0 { + status = "okay"; + + phy-handle = <&phy1>; +}; diff --git a/target/linux/ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts deleted file mode 100644 index 9b9b217f24..0000000000 --- a/target/linux/ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -#include "ar9342_ubnt_xw.dtsi" - -/ { - compatible = "ubnt,nanobeam-m5-xw", "ubnt,xw", "qca,ar9342"; - model = "Ubiquiti NanoBeam M5 (XW)"; -}; - -&mdio0 { - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - phy-mode = "mii"; - reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; - }; -}; - -ð0 { - status = "okay"; - - phy-handle = <&phy1>; -}; diff --git a/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts index c71cf11dd2..ba3ad5a8d0 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,nanostation-loco-m-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts index e359297661..fb02bb188a 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,nanostation-m-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts index 762a17b177..11bd71ca3d 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,powerbeam-m2-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts index 978a05fed6..7199d184e9 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,powerbeam-m5-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi b/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi index 899f167748..cd39410be5 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi +++ b/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi @@ -9,38 +9,6 @@ compatible = "ubnt,xw", "qca,ar9342"; model = "Ubiquiti Networks XW board"; - aliases { - led-boot = &led_link4; - led-running = &led_link4; - led-upgrade = &led_link4; - led-failsafe = &led_link4; - label-mac-device = &wmac; - }; - - leds { - compatible = "gpio-leds"; - - link1 { - label = "red:link1"; - gpios = <&gpio 11 GPIO_ACTIVE_LOW>; - }; - - link2 { - label = "orange:link2"; - gpios = <&gpio 16 GPIO_ACTIVE_LOW>; - }; - - link3 { - label = "green:link3"; - gpios = <&gpio 13 GPIO_ACTIVE_LOW>; - }; - - led_link4: link4 { - label = "green:link4"; - gpios = <&gpio 14 GPIO_ACTIVE_LOW>; - }; - }; - keys { compatible = "gpio-keys"; @@ -107,6 +75,10 @@ macaddr_art_0: macaddr@0 { reg = <0x0 0x6>; }; + + calibration_art_1000: calibration@1000 { + reg = <0x1000 0x440>; + }; }; }; }; @@ -116,7 +88,8 @@ &wmac { status = "okay"; - mtd-cal-data = <&art 0x1000>; + nvmem-cells = <&calibration_art_1000>; + nvmem-cell-names = "calibration"; }; ð0 { diff --git a/target/linux/ath79/dts/ar9342_ubnt_xw_rssileds.dtsi b/target/linux/ath79/dts/ar9342_ubnt_xw_rssileds.dtsi new file mode 100644 index 0000000000..d54dbeba38 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_ubnt_xw_rssileds.dtsi @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "ar9342_ubnt_xw.dtsi" + +#include +#include + +/ { + compatible = "ubnt,xw", "qca,ar9342"; + model = "Ubiquiti Networks XW board"; + + aliases { + led-boot = &led_link4; + led-running = &led_link4; + led-upgrade = &led_link4; + led-failsafe = &led_link4; + label-mac-device = &wmac; + }; + + leds { + compatible = "gpio-leds"; + + link1 { + label = "red:link1"; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + }; + + link2 { + label = "orange:link2"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + }; + + link3 { + label = "green:link3"; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + led_link4: link4 { + label = "green:link4"; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + }; +}; diff --git a/target/linux/ath79/dts/ar9344.dtsi b/target/linux/ath79/dts/ar9344.dtsi index fb23c53d41..dff912f8ca 100644 --- a/target/linux/ath79/dts/ar9344.dtsi +++ b/target/linux/ath79/dts/ar9344.dtsi @@ -32,7 +32,7 @@ }; &ahb { - pcie: pcie-controller@180c0000 { + pcie: pcie@180c0000 { compatible = "qcom,ar9340-pci", "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts b/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts index a45aa444de..c2c7cbb960 100644 --- a/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts +++ b/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts @@ -84,7 +84,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,0030"; reg = <0x0 0 0 0 0>; nvmem-cells = <&macaddr_art_0 1>, <&calibration_art_5000>; diff --git a/target/linux/ath79/dts/ar9344_engenius_eap600.dts b/target/linux/ath79/dts/ar9344_engenius_eap600.dts index 888e3f82ad..4d3a149e3e 100644 --- a/target/linux/ath79/dts/ar9344_engenius_eap600.dts +++ b/target/linux/ath79/dts/ar9344_engenius_eap600.dts @@ -34,7 +34,7 @@ }; &pcie { - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&macaddr_art_0 0>, <&calibration_art_5000>; nvmem-cell-names = "mac-address", "calibration"; }; diff --git a/target/linux/ath79/dts/ar9344_engenius_ecb600.dts b/target/linux/ath79/dts/ar9344_engenius_ecb600.dts index ac9bbea5d4..e7b8b9c3ce 100644 --- a/target/linux/ath79/dts/ar9344_engenius_ecb600.dts +++ b/target/linux/ath79/dts/ar9344_engenius_ecb600.dts @@ -29,7 +29,7 @@ }; &pcie { - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&macaddr_art_0 (-2)>, <&calibration_art_5000>; nvmem-cell-names = "mac-address", "calibration"; }; diff --git a/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi b/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi index c8f12a1bfb..6b1ae8ac93 100644 --- a/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi +++ b/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi @@ -56,7 +56,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,0030"; reg = <0x0 0 0 0 0>; }; diff --git a/target/linux/ath79/dts/ar9344_netgear_r6100.dts b/target/linux/ath79/dts/ar9344_netgear_r6100.dts index 419fa51f61..5952e0140f 100644 --- a/target/linux/ath79/dts/ar9344_netgear_r6100.dts +++ b/target/linux/ath79/dts/ar9344_netgear_r6100.dts @@ -203,7 +203,7 @@ &pcie { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0000 0 0 0 0>; diff --git a/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi b/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi index d2a3000004..49057548f8 100644 --- a/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi +++ b/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi @@ -90,7 +90,7 @@ #address-cells = <1>; #size-cells = <1>; - ubi@ac0000 { + ubi@0 { label = "ubi"; reg = <0x0 0x7500000>; }; @@ -171,22 +171,23 @@ reg = <0x3c0000 0x300000>; }; - kernel@6c0000 { - label = "kernel"; - reg = <0x6c0000 0x400000>; - }; - - ubiconcat0: partition@ac0000 { - label = "ubiconcat0"; - reg = <0xac0000 0x1500000>; - }; - partition@6c0000 { label = "firmware"; reg = <0x6c0000 0x1900000>; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x33373033>; - openwrt,ih-type = ; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + kernel@0 { + label = "kernel"; + reg = <0x0 0x400000>; + }; + + ubiconcat0: partition@400000 { + label = "ubiconcat0"; + reg = <0x400000 0x1500000>; + }; }; partition@1fc0000 { diff --git a/target/linux/ath79/dts/ar9344_qihoo_c301.dts b/target/linux/ath79/dts/ar9344_qihoo_c301.dts index 616036fcfc..d7e2e24239 100644 --- a/target/linux/ath79/dts/ar9344_qihoo_c301.dts +++ b/target/linux/ath79/dts/ar9344_qihoo_c301.dts @@ -48,7 +48,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; - gpio = <&gpio 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; usb_vbus: reg_usb_vbus { @@ -57,7 +57,7 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; enable-active-high; - gpio = <&gpio 19 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 19 GPIO_ACTIVE_HIGH>; }; }; @@ -103,8 +103,6 @@ pinctrl-0 = <&pmx_spi_cs1>; flash@0 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; @@ -164,8 +162,6 @@ }; flash@1 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <1>; spi-max-frequency = <25000000>; diff --git a/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi b/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi index c0e95065d5..f1d6ffda7c 100644 --- a/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi +++ b/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi @@ -59,7 +59,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,0030"; reg = <0x0 0 0 0 0>; ieee80211-freq-limit = <2402000 2482000>; diff --git a/target/linux/ath79/dts/ar9344_watchguard_ap100.dts b/target/linux/ath79/dts/ar9344_watchguard_ap100.dts index 2fd9a6e51b..e09d539c56 100644 --- a/target/linux/ath79/dts/ar9344_watchguard_ap100.dts +++ b/target/linux/ath79/dts/ar9344_watchguard_ap100.dts @@ -63,7 +63,7 @@ &pcie { status = "disabled"; - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&calibration_art_5000>; nvmem-cell-names = "calibration"; }; diff --git a/target/linux/ath79/dts/ar9344_watchguard_ap200.dts b/target/linux/ath79/dts/ar9344_watchguard_ap200.dts index 9cf6819958..c3d7c50813 100644 --- a/target/linux/ath79/dts/ar9344_watchguard_ap200.dts +++ b/target/linux/ath79/dts/ar9344_watchguard_ap200.dts @@ -61,7 +61,7 @@ }; &pcie { - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&macaddr_art_0 (-1)>, <&calibration_art_5000>; nvmem-cell-names = "mac-address", "calibration"; }; diff --git a/target/linux/ath79/dts/ar934x.dtsi b/target/linux/ath79/dts/ar934x.dtsi index 94dfde4125..98cd76629f 100644 --- a/target/linux/ath79/dts/ar934x.dtsi +++ b/target/linux/ath79/dts/ar934x.dtsi @@ -197,9 +197,6 @@ nand-ecc-mode = "hw"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; }; diff --git a/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts b/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts index 1c6dcee8bf..b81485f465 100644 --- a/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts +++ b/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts @@ -72,7 +72,6 @@ wifi@0,0 { compatible = "qcom,ath10k"; reg = <0 0 0 0 0>; - device_type = "pci"; }; }; diff --git a/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts b/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts index 227f57b9b4..6f96b61392 100644 --- a/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts +++ b/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts @@ -11,7 +11,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-always-on; }; diff --git a/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi b/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi index e7044b60a4..f17dd513e2 100644 --- a/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi +++ b/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi @@ -53,8 +53,6 @@ status = "okay"; flash@0 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; diff --git a/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts b/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts index 762197f255..c3d42a8b35 100644 --- a/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts +++ b/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts @@ -95,8 +95,6 @@ status = "okay"; flash@0 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; diff --git a/target/linux/ath79/dts/qca953x.dtsi b/target/linux/ath79/dts/qca953x.dtsi index 4300c741ad..cc26db5ba2 100644 --- a/target/linux/ath79/dts/qca953x.dtsi +++ b/target/linux/ath79/dts/qca953x.dtsi @@ -150,7 +150,7 @@ reg = <0x18070000 0x4>; }; - pcie0: pcie-controller@180c0000 { + pcie0: pcie@180c0000 { compatible = "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts b/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts index 59dd83d5f8..4a68f53075 100644 --- a/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts +++ b/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts @@ -75,7 +75,7 @@ &pcie0 { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0 0 0 0 0>; }; diff --git a/target/linux/ath79/dts/qca9558_aruba_ap-115.dts b/target/linux/ath79/dts/qca9558_aruba_ap-115.dts index c15cb677b9..9d95282451 100644 --- a/target/linux/ath79/dts/qca9558_aruba_ap-115.dts +++ b/target/linux/ath79/dts/qca9558_aruba_ap-115.dts @@ -83,7 +83,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 3 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-always-on; }; diff --git a/target/linux/ath79/dts/qca9558_engenius_esr900.dts b/target/linux/ath79/dts/qca9558_engenius_esr900.dts index 269f743223..ef0e21a3b5 100644 --- a/target/linux/ath79/dts/qca9558_engenius_esr900.dts +++ b/target/linux/ath79/dts/qca9558_engenius_esr900.dts @@ -76,7 +76,7 @@ &pcie0 { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "pci168c,0033"; reg = <0x0000 0 0 0 0>; nvmem-cells = <&calibration_art_5000>; diff --git a/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts b/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts index 6cd93f6b33..ee2e82ef10 100644 --- a/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts +++ b/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts @@ -109,7 +109,7 @@ &mdio0 { status = "okay"; - switch { + switch@0 { compatible = "qca,ar8327"; reg = <0>; diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-911g-5hpacd.dts b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-911g-5hpacd.dts new file mode 100644 index 0000000000..22784075f6 --- /dev/null +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-911g-5hpacd.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca9558_mikrotik_routerboard-92x.dtsi" + +/ { + compatible = "mikrotik,routerboard-911g-5hpacd", "qca,qca9558"; + model = "MikroTik RouterBOARD 911G-5HPacD"; + + ath10k-leds { + compatible = "gpio-leds"; + + wlan5g { + label = "green:wlan5g"; + gpios = <&ath10k 0 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + }; +}; + +&pcie1 { + status = "okay"; + + ath10k: wifi@0,0 { + compatible = "qcom,ath10k"; + reg = <0 0 0 0 0>; + #gpio-cells = <2>; + gpio-controller; + }; +}; diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts index d1f307bd48..36283ec228 100644 --- a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts @@ -17,6 +17,14 @@ }; }; +&mdio1 { + status = "okay"; +}; + +ð1 { + status = "okay"; +}; + &pcie1 { status = "okay"; diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts index 8ad834fe61..553dff0853 100644 --- a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts @@ -25,6 +25,14 @@ }; }; +&mdio1 { + status = "okay"; +}; + +ð1 { + status = "okay"; +}; + &pcie0 { status = "okay"; diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi index 82b8c2ae56..bc85cad9b3 100644 --- a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi @@ -86,8 +86,6 @@ }; &mdio1 { - status = "okay"; - phy_sfp: ethernet-phy@0 { reg = <0>; phy-mode = "sgmii"; @@ -96,8 +94,6 @@ }; ð1 { - status = "okay"; - phy-handle = <&phy_sfp>; pll-data = <0x03000000 0x00000101 0x00001616>; qca955x-sgmii-fixup; diff --git a/target/linux/ath79/dts/qca9558_sophos_ap.dtsi b/target/linux/ath79/dts/qca9558_sophos_ap.dtsi index 8abd3e60b7..0cf5eb6e66 100644 --- a/target/linux/ath79/dts/qca9558_sophos_ap.dtsi +++ b/target/linux/ath79/dts/qca9558_sophos_ap.dtsi @@ -62,7 +62,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; status = "disabled"; diff --git a/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi b/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi index c4d910bf1e..35532f42c8 100644 --- a/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi +++ b/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi @@ -72,7 +72,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 21 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 21 GPIO_ACTIVE_HIGH>; enable-active-high; }; @@ -81,7 +81,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 22 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts b/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts index 9aee8c362c..20230e684e 100644 --- a/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts +++ b/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts @@ -143,16 +143,20 @@ firmware@500000 { label = "firmware"; reg = <0x500000 0x7b00000>; - }; - partition@500000 { - label = "kernel"; - reg = <0x500000 0x400000>; - }; + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - partition@900000 { - label = "ubi"; - reg = <0x900000 0x7700000>; + partition@0 { + label = "kernel"; + reg = <0x0 0x400000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x400000 0x7700000>; + }; }; }; }; diff --git a/target/linux/ath79/dts/qca955x.dtsi b/target/linux/ath79/dts/qca955x.dtsi index e7daa9d827..c17a15c55e 100644 --- a/target/linux/ath79/dts/qca955x.dtsi +++ b/target/linux/ath79/dts/qca955x.dtsi @@ -185,7 +185,7 @@ reg = <0x18070000 0x58>; }; - pcie0: pcie-controller@180c0000 { + pcie0: pcie@180c0000 { compatible = "qcom,qca9550-pci", "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; @@ -222,7 +222,7 @@ status = "disabled"; }; - pcie1: pcie-controller@18250000 { + pcie1: pcie@18250000 { compatible = "qcom,qca9550-pci", "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; @@ -313,9 +313,6 @@ nand-ecc-mode = "hw"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; }; diff --git a/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi b/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi index e448cd3012..66f2e38853 100644 --- a/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi +++ b/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi @@ -119,7 +119,7 @@ &pcie0 { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/qca955x_senao_loader.dtsi b/target/linux/ath79/dts/qca955x_senao_loader.dtsi index cf82c050b6..31e00ce063 100644 --- a/target/linux/ath79/dts/qca955x_senao_loader.dtsi +++ b/target/linux/ath79/dts/qca955x_senao_loader.dtsi @@ -26,16 +26,16 @@ }; &pcie0 { - ath10k_0: wifi@0,0,0 { + ath10k_0: wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0 0 0 0 0>; }; }; &pcie1 { - ath10k_1: wifi@0,1,0 { + ath10k_1: wifi@0,0 { compatible = "qcom,ath10k"; - reg = <0x0 1 0 0 0>; + reg = <0x0 0 0 0 0>; }; }; diff --git a/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi b/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi index 61446263c4..8f62cf442c 100644 --- a/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi +++ b/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi @@ -43,7 +43,7 @@ &pcie0 { status = "okay"; - ath10k_0: wifi@0,0,0 { + ath10k_0: wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0000 0 0 0 0>; }; diff --git a/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts b/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts index 04567e6b88..8767693c82 100644 --- a/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts +++ b/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts @@ -86,9 +86,9 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_uboot_0fc00: macaddr@0fc00 { + macaddr_uboot_fc00: macaddr@fc00 { compatible = "mac-base"; - reg = <0x0fc00 0x6>; + reg = <0xfc00 0x6>; #nvmem-cell-cells = <1>; }; }; @@ -134,7 +134,7 @@ compatible = "qcom,ath10k"; reg = <0 0 0 0 0>; - nvmem-cells = <&macaddr_uboot_0fc00 (-2)>, <&calibration_ath10k>; + nvmem-cells = <&macaddr_uboot_fc00 (-2)>, <&calibration_ath10k>; nvmem-cell-names = "mac-address", "calibration"; }; }; @@ -148,21 +148,21 @@ phy-handle = <&swphy4>; - nvmem-cells = <&macaddr_uboot_0fc00 1>; + nvmem-cells = <&macaddr_uboot_fc00 1>; nvmem-cell-names = "mac-address"; }; ð1 { status = "okay"; - nvmem-cells = <&macaddr_uboot_0fc00 0>; + nvmem-cells = <&macaddr_uboot_fc00 0>; nvmem-cell-names = "mac-address"; }; &wmac { status = "okay"; - nvmem-cells = <&macaddr_uboot_0fc00 (-1)>, <&calibration_ath9k>; + nvmem-cells = <&macaddr_uboot_fc00 (-1)>, <&calibration_ath9k>; nvmem-cell-names = "mac-address", "calibration"; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts index 9c1e82bf98..c3f1a130eb 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts index 73700b626f..1fac6082cf 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts index 1e100b31a7..9d06a49626 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts @@ -56,12 +56,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - calibration_ath10k: calibration@5000 { reg = <0x5000 0x844>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts index 32fba98051..5139bc7670 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts index 1c48775cdf..6e7ba5fede 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts b/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts index e7f21fafa5..af133813e7 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts @@ -49,12 +49,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - calibration_ath10k: calibration@5000 { reg = <0x5000 0x844>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi b/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi index 9e0b97fcbf..3b36049d5e 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi +++ b/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi @@ -55,6 +55,18 @@ label = "info"; reg = <0x030000 0x010000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_info_8: macaddr@8 { + compatible = "mac-base"; + reg = <0x8 0x6>; + #nvmem-cell-cells = <1>; + }; + }; }; partition@40000 { diff --git a/target/linux/ath79/dts/qca9563_ubnt_uk-ultra.dts b/target/linux/ath79/dts/qca9563_ubnt_uk-ultra.dts new file mode 100644 index 0000000000..1ba635117e --- /dev/null +++ b/target/linux/ath79/dts/qca9563_ubnt_uk-ultra.dts @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca9563_ubnt_unifiac-lite.dtsi" + +/ { + compatible = "ubnt,uk-ultra", "qca,qca9563"; + model = "Ubiquiti UniFi Swiss Army Knife Ultra"; +}; + +&leds { + led-rssi0 { + label = "white:rssi0"; + gpios = <&gpio 21 GPIO_ACTIVE_HIGH>; + }; + + led-rssi1 { + label = "white:rssi1"; + gpios = <&gpio 20 GPIO_ACTIVE_HIGH>; + }; + + led-rssi2 { + label = "white:rssi2"; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; + }; + + led-rssi3 { + label = "white:rssi3"; + gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + }; +}; + +/** + * Antenna selection on GPIO5 and GPIO6 + * High = Internal ; Low = External + */ diff --git a/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi b/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi index da01251f3b..60d6fbc895 100644 --- a/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi +++ b/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi @@ -13,7 +13,7 @@ led-upgrade = &led_blue; }; - leds { + leds: leds { compatible = "gpio-leds"; led_white: led_white { diff --git a/target/linux/ath79/dts/qca956x.dtsi b/target/linux/ath79/dts/qca956x.dtsi index e46f0676e2..8b261568f0 100644 --- a/target/linux/ath79/dts/qca956x.dtsi +++ b/target/linux/ath79/dts/qca956x.dtsi @@ -157,7 +157,7 @@ status = "disabled"; }; - pcie: pcie-controller@18250000 { + pcie: pcie@18250000 { compatible = "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h index 0773f1a5af..fca072a83a 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h @@ -310,11 +310,11 @@ ag71xx_ring_size_order(int size) #define FIFO_CFG4_MC BIT(8) /* Multicast Packet */ #define FIFO_CFG4_BC BIT(9) /* Broadcast Packet */ #define FIFO_CFG4_DR BIT(10) /* Dribble */ -#define FIFO_CFG4_LE BIT(11) /* Long Event */ -#define FIFO_CFG4_CF BIT(12) /* Control Frame */ -#define FIFO_CFG4_PF BIT(13) /* Pause Frame */ -#define FIFO_CFG4_UO BIT(14) /* Unsupported Opcode */ -#define FIFO_CFG4_VT BIT(15) /* VLAN tag detected */ +#define FIFO_CFG4_CF BIT(11) /* Control Frame */ +#define FIFO_CFG4_PF BIT(12) /* Pause Frame */ +#define FIFO_CFG4_UO BIT(13) /* Unsupported Opcode */ +#define FIFO_CFG4_VT BIT(14) /* VLAN tag detected */ +#define FIFO_CFG4_LE BIT(15) /* Long Event */ #define FIFO_CFG4_FT BIT(16) /* Frame Truncated */ #define FIFO_CFG4_UC BIT(17) /* Unicast Packet */ @@ -322,20 +322,20 @@ ag71xx_ring_size_order(int size) #define FIFO_CFG5_DV BIT(1) /* RX_DV Event */ #define FIFO_CFG5_FC BIT(2) /* False Carrier */ #define FIFO_CFG5_CE BIT(3) /* Code Error */ -#define FIFO_CFG5_LM BIT(4) /* Length Mismatch */ -#define FIFO_CFG5_LO BIT(5) /* Length Out of Range */ -#define FIFO_CFG5_OK BIT(6) /* Packet is OK */ -#define FIFO_CFG5_MC BIT(7) /* Multicast Packet */ -#define FIFO_CFG5_BC BIT(8) /* Broadcast Packet */ -#define FIFO_CFG5_DR BIT(9) /* Dribble */ -#define FIFO_CFG5_CF BIT(10) /* Control Frame */ -#define FIFO_CFG5_PF BIT(11) /* Pause Frame */ -#define FIFO_CFG5_UO BIT(12) /* Unsupported Opcode */ -#define FIFO_CFG5_VT BIT(13) /* VLAN tag detected */ -#define FIFO_CFG5_LE BIT(14) /* Long Event */ -#define FIFO_CFG5_FT BIT(15) /* Frame Truncated */ -#define FIFO_CFG5_16 BIT(16) /* unknown */ -#define FIFO_CFG5_17 BIT(17) /* unknown */ +#define FIFO_CFG5_CR BIT(4) /* CRC error */ +#define FIFO_CFG5_LM BIT(5) /* Length Mismatch */ +#define FIFO_CFG5_LO BIT(6) /* Length out of range */ +#define FIFO_CFG5_OK BIT(7) /* Packet is OK */ +#define FIFO_CFG5_MC BIT(8) /* Multicast Packet */ +#define FIFO_CFG5_BC BIT(9) /* Broadcast Packet */ +#define FIFO_CFG5_DR BIT(10) /* Dribble */ +#define FIFO_CFG5_CF BIT(11) /* Control Frame */ +#define FIFO_CFG5_PF BIT(12) /* Pause Frame */ +#define FIFO_CFG5_UO BIT(13) /* Unsupported Opcode */ +#define FIFO_CFG5_VT BIT(14) /* VLAN tag detected */ +#define FIFO_CFG5_LE BIT(15) /* Long Event */ +#define FIFO_CFG5_FT BIT(16) /* Frame Truncated */ +#define FIFO_CFG5_UC BIT(17) /* Unicast Packet */ #define FIFO_CFG5_SF BIT(18) /* Short Frame */ #define FIFO_CFG5_BM BIT(19) /* Byte Mode */ diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c index e5adc821d2..b022a3e9fb 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c @@ -169,8 +169,7 @@ static void ag71xx_ethtool_get_strings(struct net_device *netdev, u32 sset, int i; for (i = 0; i < ARRAY_SIZE(ag71xx_statistics); i++) - memcpy(data + i * ETH_GSTRING_LEN, - ag71xx_statistics[i].name, ETH_GSTRING_LEN); + ethtool_puts(&data, ag71xx_statistics[i].name); } } diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c index 8f95210e0f..8a5cd3bcde 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c @@ -407,11 +407,11 @@ static void ag71xx_dma_reset(struct ag71xx *ag) FIFO_CFG4_VT) #define FIFO_CFG5_INIT (FIFO_CFG5_DE | FIFO_CFG5_DV | FIFO_CFG5_FC | \ - FIFO_CFG5_CE | FIFO_CFG5_LO | FIFO_CFG5_OK | \ - FIFO_CFG5_MC | FIFO_CFG5_BC | FIFO_CFG5_DR | \ - FIFO_CFG5_CF | FIFO_CFG5_PF | FIFO_CFG5_VT | \ - FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \ - FIFO_CFG5_17 | FIFO_CFG5_SF) + FIFO_CFG5_CE | FIFO_CFG5_LM | FIFO_CFG5_LO | \ + FIFO_CFG5_OK | FIFO_CFG5_MC | FIFO_CFG5_BC | \ + FIFO_CFG5_DR | FIFO_CFG5_CF | FIFO_CFG5_UO | \ + FIFO_CFG5_VT | FIFO_CFG5_LE | FIFO_CFG5_FT | \ + FIFO_CFG5_UC | FIFO_CFG5_SF) static void ag71xx_hw_stop(struct ag71xx *ag) { diff --git a/target/linux/ath79/generic/base-files/etc/board.d/01_leds b/target/linux/ath79/generic/base-files/etc/board.d/01_leds index 615abe4b3b..525224bec9 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/01_leds +++ b/target/linux/ath79/generic/base-files/etc/board.d/01_leds @@ -27,7 +27,8 @@ pcs,cap324|\ tplink,cpe605-v1|\ tplink,cpe610-v1|\ tplink,cpe610-v2|\ -tplink,tl-wa1201-v2) +tplink,tl-wa1201-v2|\ +ubnt,litebeam-m5-xw) ucidef_set_led_netdev "lan" "LAN" "green:lan" "eth0" ;; tplink,tl-wdr6500-v2) @@ -516,6 +517,13 @@ ubnt,rocket-m) ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "green:link3" "wlan0" "51" "100" ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "green:link4" "wlan0" "76" "100" ;; +ubnt,uk-ultra) + ucidef_set_rssimon "wlan0" "200000" "1" + ucidef_set_led_rssi "rssilow" "RSSILOW" "white:rssi0" "wlan0" "1" "100" + ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "white:rssi1" "wlan0" "26" "100" + ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "white:rssi2" "wlan0" "51" "100" + ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "white:rssi3" "wlan0" "76" "100" + ;; wallys,dr531) ucidef_set_led_netdev "lan" "LAN" "green:lan" "eth0" ucidef_set_led_switch "wan" "WAN" "green:wan" "switch0" "0x2" diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network index b74a7ff6b4..01747acae0 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/02_network +++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network @@ -105,6 +105,7 @@ ath79_setup_interfaces() ubnt,bullet-m-xw|\ ubnt,lap-120|\ ubnt,litebeam-ac-gen2|\ + ubnt,litebeam-m5-xw|\ ubnt,nanobeam-ac|\ ubnt,nanobeam-ac-xc|\ ubnt,nanostation-ac-loco|\ @@ -116,6 +117,7 @@ ath79_setup_interfaces() ubnt,powerbridge-m|\ ubnt,rocket-5ac-lite|\ ubnt,rocket-m|\ + ubnt,uk-ultra|\ ubnt,unifiac-lite|\ ubnt,unifiac-lr|\ ubnt,unifiac-mesh|\ diff --git a/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches b/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches index 899a8ba97e..279f518409 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches +++ b/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches @@ -92,6 +92,10 @@ ubnt,nanostation-m) ubnt,nanostation-m-xw) ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "2" ;; +ubnt,uk-ultra) + ucidef_add_gpio_switch "ant0_internal" "ANT0 Internal" "5" "1" + ucidef_add_gpio_switch "ant1_internal" "ANT1 Internal" "6" "1" + ;; zbtlink,zbt-wd323) ucidef_add_gpio_switch "io0" "IO#0" "0" ucidef_add_gpio_switch "io1" "IO#1" "1" diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index dd627ad2d6..1acbf35947 100644 --- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -37,6 +37,7 @@ case "$FIRMWARE" in sophos,ap100|\ sophos,ap100c|\ ubnt,bullet-ac|\ + ubnt,uk-ultra|\ ubnt,unifiac-lite|\ ubnt,unifiac-lr|\ ubnt,unifiac-mesh|\ diff --git a/target/linux/ath79/image/common-ubnt.mk b/target/linux/ath79/image/common-ubnt.mk index 76d6de000b..f44e06e110 100644 --- a/target/linux/ath79/image/common-ubnt.mk +++ b/target/linux/ath79/image/common-ubnt.mk @@ -121,6 +121,13 @@ define Device/ubnt-xw UBNT_VERSION := 6.0.4 endef +define Device/ubnt_unifiac + DEVICE_VENDOR := Ubiquiti + SOC := qca9563 + IMAGE_SIZE := 15488k + DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct +endef + define Device/ubnt-unifi-jffs2 $(Device/ubnt) KERNEL_SIZE := 3072k diff --git a/target/linux/ath79/image/generic-ubnt.mk b/target/linux/ath79/image/generic-ubnt.mk index fa4daa3aaa..a4d118456f 100644 --- a/target/linux/ath79/image/generic-ubnt.mk +++ b/target/linux/ath79/image/generic-ubnt.mk @@ -28,6 +28,9 @@ TARGET_DEVICES += ubnt_bullet-ac define Device/ubnt_bullet-m-xw $(Device/ubnt-xw) DEVICE_MODEL := Bullet M + DEVICE_ALT0_VENDOR := Ubiquiti + DEVICE_ALT0_MODEL := Rocket M + DEVICE_ALT0_VARIANT := XW DEVICE_PACKAGES += rssileds SUPPORTED_DEVICES += bullet-m-xw endef @@ -62,6 +65,14 @@ define Device/ubnt_litebeam-ac-gen2 endef TARGET_DEVICES += ubnt_litebeam-ac-gen2 +define Device/ubnt_litebeam-m5-xw + $(Device/ubnt-xw) + DEVICE_MODEL := LiteBeam M5 + SUPPORTED_DEVICES += lbe-m5 + DEVICE_PACKAGES := -kmod-usb2 +endef +TARGET_DEVICES += ubnt_litebeam-m5-xw + define Device/ubnt_nanobeam-ac $(Device/ubnt-wa) DEVICE_MODEL := NanoBeam AC @@ -87,14 +98,6 @@ define Device/ubnt_nanobeam-ac-xc endef TARGET_DEVICES += ubnt_nanobeam-ac-xc -define Device/ubnt_nanobeam-m5-xw - $(Device/ubnt-xw) - DEVICE_MODEL := NanoBeam M5 - DEVICE_PACKAGES += rssileds - SUPPORTED_DEVICES += loco-m-xw -endef -TARGET_DEVICES += ubnt_nanobeam-m5-xw - define Device/ubnt_nanostation-ac $(Device/ubnt-wa) DEVICE_MODEL := Nanostation AC @@ -112,8 +115,17 @@ TARGET_DEVICES += ubnt_nanostation-ac-loco define Device/ubnt_nanostation-loco-m-xw $(Device/ubnt-xw) DEVICE_MODEL := Nanostation Loco M - DEVICE_PACKAGES += rssileds - SUPPORTED_DEVICES += loco-m-xw + DEVICE_PACKAGES += rssileds -kmod-usb2 + DEVICE_ALT0_VENDOR := Ubiquiti + DEVICE_ALT0_MODEL := AirGrid M5 HP + DEVICE_ALT0_VARIANT := XW + DEVICE_ALT1_VENDOR := Ubiquiti + DEVICE_ALT1_MODEL := PowerBeam M5 300 + DEVICE_ALT1_VARIANT := XW + DEVICE_ALT2_VENDOR := Ubiquiti + DEVICE_ALT2_MODEL := NanoBeam M5 + DEVICE_ALT2_VARIANT := XW + SUPPORTED_DEVICES += loco-m-xw nanostation-m-xw ubnt,nanobeam-m5-xw endef TARGET_DEVICES += ubnt_nanostation-loco-m-xw @@ -229,6 +241,13 @@ define Device/ubnt_routerstation-pro endef TARGET_DEVICES += ubnt_routerstation-pro +define Device/ubnt_uk-ultra + $(Device/ubnt_unifiac) + DEVICE_MODEL := UniFi Swiss Army Knife Ultra + DEVICE_PACKAGES += rssileds -swconfig +endef +TARGET_DEVICES += ubnt_uk-ultra + define Device/ubnt_unifi-ap $(Device/ubnt-bz) DEVICE_MODEL := UniFi AP @@ -244,13 +263,6 @@ define Device/ubnt_unifi-ap-lr endef TARGET_DEVICES += ubnt_unifi-ap-lr -define Device/ubnt_unifiac - DEVICE_VENDOR := Ubiquiti - SOC := qca9563 - IMAGE_SIZE := 15488k - DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct -endef - define Device/ubnt_unifiac-lite $(Device/ubnt_unifiac) DEVICE_MODEL := UniFi AC Lite diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index d26420c7f5..19cbf30933 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -28,15 +28,37 @@ define Device/mikrotik_routerboard-911-lite endef TARGET_DEVICES += mikrotik_routerboard-911-lite +define Device/mikrotik_routerboard-911g-xhpnd + $(Device/mikrotik_nand) + SOC := ar9342 + DEVICE_MODEL := RouterBOARD 911G-2HPnD + DEVICE_ALT0_VENDOR := Mikrotik + DEVICE_ALT0_MODEL := RouterBOARD 911G-5HPnD + DEVICE_PACKAGES += rssileds + SUPPORTED_DEVICES += rb-912uag-2hpnd +endef +TARGET_DEVICES += mikrotik_routerboard-911g-xhpnd + define Device/mikrotik_routerboard-912uag-2hpnd $(Device/mikrotik_nand) SOC := ar9342 DEVICE_MODEL := RouterBOARD 912UAG-2HPnD - DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 + DEVICE_ALT0_VENDOR := Mikrotik + DEVICE_ALT0_MODEL := RouterBOARD 912UAG-5HPnD + DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 rssileds SUPPORTED_DEVICES += rb-912uag-2hpnd endef TARGET_DEVICES += mikrotik_routerboard-912uag-2hpnd +define Device/mikrotik_routerboard-911g-5hpacd + $(Device/mikrotik_nand) + SOC := qca9558 + DEVICE_MODEL := RouterBOARD 911G-5HPacD + DEVICE_PACKAGES += kmod-ath10k-ct ath10k-firmware-qca988x-ct + SUPPORTED_DEVICES += rb-921gs-5hpacd-r2 +endef +TARGET_DEVICES += mikrotik_routerboard-911g-5hpacd + define Device/mikrotik_routerboard-921gs-5hpacd-15s $(Device/mikrotik_nand) SOC := qca9558 diff --git a/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds b/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds index 66fa2ee6ac..16cb628445 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds +++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds @@ -16,6 +16,15 @@ mikrotik,routerboard-lhg-5nd) ucidef_set_led_rssi "rssimediumhigh" "rssimediumhigh" "green:rssimediumhigh" "wlan0" "60" "100" ucidef_set_led_rssi "rssihigh" "rssihigh" "green:rssihigh" "wlan0" "80" "100" ;; +mikrotik,routerboard-911g-xhpnd|\ +mikrotik,routerboard-912uag-2hpnd) + ucidef_set_rssimon "wlan0" "200000" "1" + ucidef_set_led_rssi "rssilow" "rssilow" "green:led1" "wlan0" "1" "100" + ucidef_set_led_rssi "rssimediumlow" "rssimediumlow" "green:led2" "wlan0" "20" "100" + ucidef_set_led_rssi "rssimedium" "rssimedium" "green:led3" "wlan0" "40" "100" + ucidef_set_led_rssi "rssimediumhigh" "rssimediumhigh" "green:led4" "wlan0" "60" "100" + ucidef_set_led_rssi "rssihigh" "rssihigh" "green:led5" "wlan0" "80" "100" + ;; mikrotik,routerboard-750-r2|\ mikrotik,routerboard-951ui-2hnd|\ mikrotik,routerboard-951ui-2nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network index d45af6dbb3..4da5884045 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network @@ -20,6 +20,7 @@ ath79_setup_interfaces() "0@eth0" "1:lan:4" "2:lan:1" "3:lan:3" "4:lan:2" ;; mikrotik,routerboard-911-lite|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-lhg-5nd|\ @@ -61,6 +62,8 @@ ath79_setup_macs() case "$board" in mikrotik,routerboard-911-lite|\ + mikrotik,routerboard-911g-5hpacd|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-lhg-5nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom index cc05ba080b..e7bf17d0ec 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +++ b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom @@ -24,6 +24,7 @@ case "$FIRMWARE" in "ath9k-eeprom-ahb-18100000.wmac.bin") case $board in mikrotik,routerboard-911-lite|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-lhg-5nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index 5b918d966c..da331dc0ea 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -11,6 +11,7 @@ board=$(board_name) case "$FIRMWARE" in "ath10k/cal-pci-0000:00:00.0.bin") case $board in + mikrotik,routerboard-911g-5hpacd|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-951ui-2nd|\ mikrotik,routerboard-952ui-5ac2nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh index e3887bfc50..c4d401b8ae 100644 --- a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh +++ b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh @@ -30,6 +30,8 @@ platform_do_upgrade() { case "$board" in mikrotik,routerboard-493g|\ + mikrotik,routerboard-911g-5hpacd|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-922uags-5hpacd|\ diff --git a/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch b/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch new file mode 100644 index 0000000000..7aa501514d --- /dev/null +++ b/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch @@ -0,0 +1,33 @@ +From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 9 Jan 2024 20:48:46 +0100 +Subject: [PATCH] reset: ath79: read back reset register + +Read back the reset register in order to flush the cache. This fixes +spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel +DRAM chips. + +This issue was fixed in the past, but switching to the reset-driver +specific implementation removed the old fix. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 +Link: https://github.com/openwrt/openwrt/issues/13043 +Link: https://dev.archive.openwrt.org/ticket/17839 +Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") + +Signed-off-by: David Bauer +--- + drivers/reset/reset-ath79.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res + else + val &= ~BIT(id); + writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; diff --git a/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch index bf7eb691a5..cf0a75c791 100644 --- a/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch +++ b/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch @@ -37,7 +37,7 @@ Signed-off-by: John Crispin +- interrupt-parent: phandle to the MIPS IRQ controller + +* Example for ar7100 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qca,ar7100-pci"; + #address-cells = <3>; + #size-cells = <2>; diff --git a/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch index a0af79cb4d..a32c9bdcde 100644 --- a/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch +++ b/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch @@ -39,7 +39,7 @@ Signed-off-by: John Crispin +- interrupt-controller: define to enable the builtin IRQ cascade. + +* Example for qca9557 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qcom,ar7240-pci"; + #address-cells = <3>; + #size-cells = <2>; diff --git a/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch b/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch new file mode 100644 index 0000000000..7aa501514d --- /dev/null +++ b/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch @@ -0,0 +1,33 @@ +From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 9 Jan 2024 20:48:46 +0100 +Subject: [PATCH] reset: ath79: read back reset register + +Read back the reset register in order to flush the cache. This fixes +spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel +DRAM chips. + +This issue was fixed in the past, but switching to the reset-driver +specific implementation removed the old fix. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 +Link: https://github.com/openwrt/openwrt/issues/13043 +Link: https://dev.archive.openwrt.org/ticket/17839 +Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") + +Signed-off-by: David Bauer +--- + drivers/reset/reset-ath79.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res + else + val &= ~BIT(id); + writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; diff --git a/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch index bf7eb691a5..cf0a75c791 100644 --- a/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch +++ b/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch @@ -37,7 +37,7 @@ Signed-off-by: John Crispin +- interrupt-parent: phandle to the MIPS IRQ controller + +* Example for ar7100 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qca,ar7100-pci"; + #address-cells = <3>; + #size-cells = <2>; diff --git a/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch index a0af79cb4d..a32c9bdcde 100644 --- a/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch +++ b/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch @@ -39,7 +39,7 @@ Signed-off-by: John Crispin +- interrupt-controller: define to enable the builtin IRQ cascade. + +* Example for qca9557 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qcom,ar7240-pci"; + #address-cells = <3>; + #size-cells = <2>; diff --git a/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch b/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch index 1a2d4426ab..2235c28fd9 100644 --- a/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch @@ -336,7 +336,7 @@ SVN-Revision: 35130 #endif /* _LINUX_TYPES_H */ --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c -@@ -1494,8 +1494,8 @@ struct sk_buff *inet_gro_receive(struct +@@ -1512,8 +1512,8 @@ struct sk_buff *inet_gro_receive(struct if (unlikely(ip_fast_csum((u8 *)iph, 5))) goto out; diff --git a/target/linux/bcm27xx/Makefile b/target/linux/bcm27xx/Makefile index 99c5fa75aa..d7b56b23bc 100644 --- a/target/linux/bcm27xx/Makefile +++ b/target/linux/bcm27xx/Makefile @@ -9,7 +9,7 @@ ARCH:=arm BOARD:=bcm27xx BOARDNAME:=Broadcom BCM27xx FEATURES:=audio boot-part display ext4 fpu gpio rootfs-part rtc squashfs usb usbgadget -SUBTARGETS:=bcm2708 bcm2709 bcm2710 bcm2711 +SUBTARGETS:=bcm2708 bcm2709 bcm2710 bcm2711 bcm2712 KERNEL_PATCHVER:=6.1 @@ -22,7 +22,7 @@ include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES := $(filter-out urngd,$(DEFAULT_PACKAGES)) DEFAULT_PACKAGES += \ - bcm27xx-gpu-fw \ + bcm27xx-gpu-fw bcm27xx-utils \ kmod-usb-hid \ kmod-sound-core kmod-sound-arm-bcm2835 \ kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \ diff --git a/target/linux/bcm27xx/base-files/etc/board.d/02_network b/target/linux/bcm27xx/base-files/etc/board.d/02_network index 23bc9afdb9..f246139c38 100644 --- a/target/linux/bcm27xx/base-files/etc/board.d/02_network +++ b/target/linux/bcm27xx/base-files/etc/board.d/02_network @@ -17,6 +17,7 @@ raspberrypi,3-model-b-plus |\ raspberrypi,400 |\ raspberrypi,4-compute-module |\ raspberrypi,4-model-b |\ +raspberrypi,5-model-b |\ raspberrypi,model-b |\ raspberrypi,model-b-plus |\ raspberrypi,model-b-rev2) diff --git a/target/linux/bcm27xx/base-files/etc/diag.sh b/target/linux/bcm27xx/base-files/etc/diag.sh index 180b31ec95..92d72bea11 100644 --- a/target/linux/bcm27xx/base-files/etc/diag.sh +++ b/target/linux/bcm27xx/base-files/etc/diag.sh @@ -14,6 +14,7 @@ set_state() { raspberrypi,400 |\ raspberrypi,4-compute-module |\ raspberrypi,4-model-b |\ + raspberrypi,5-model-b |\ raspberrypi,model-b-plus) status_led="led1" ;; diff --git a/target/linux/bcm27xx/bcm2708/config-6.1 b/target/linux/bcm27xx/bcm2708/config-6.1 index c5d604e6bc..cef17940a3 100644 --- a/target/linux/bcm27xx/bcm2708/config-6.1 +++ b/target/linux/bcm27xx/bcm2708/config-6.1 @@ -30,7 +30,6 @@ CONFIG_ARM_UNWIND=y CONFIG_AUTO_ZRELADDR=y CONFIG_BCM2708_VCMEM=y # CONFIG_BCM2711_THERMAL is not set -CONFIG_BCM2835_DEVGPIOMEM=y CONFIG_BCM2835_FAST_MEMCPY=y CONFIG_BCM2835_MBOX=y CONFIG_BCM2835_POWER=y @@ -151,7 +150,6 @@ CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CMDLINE=y -# CONFIG_FB_RPISENSE is not set CONFIG_FB_SIMPLE=y CONFIG_FIQ=y CONFIG_FIXED_PHY=y @@ -239,8 +237,6 @@ CONFIG_MDIO_DEVRES=y CONFIG_MEMFD_CREATE=y CONFIG_MEMORY_ISOLATION=y CONFIG_MFD_CORE=y -# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set -# CONFIG_MFD_RPISENSE_CORE is not set CONFIG_MFD_SYSCON=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y CONFIG_MIGRATION=y @@ -266,6 +262,7 @@ CONFIG_NO_HZ=y CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_CONFIGFS=y @@ -296,7 +293,6 @@ CONFIG_PM_GENERIC_DOMAINS_OF=y CONFIG_PM_GENERIC_DOMAINS_SLEEP=y CONFIG_PM_OPP=y CONFIG_PM_SLEEP=y -# CONFIG_PM_USERSPACE_AUTOSLEEP is not set CONFIG_POWER_SUPPLY=y CONFIG_PREEMPT_NONE_BUILD=y CONFIG_PRINTK_TIME=y @@ -306,6 +302,7 @@ CONFIG_PWM_BCM2835=y CONFIG_PWM_SYSFS=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RASPBERRYPI_FIRMWARE=y +CONFIG_RASPBERRYPI_GPIOMEM=y CONFIG_RASPBERRYPI_POWER=y CONFIG_RATIONAL=y # CONFIG_RAVE_SP_CORE is not set diff --git a/target/linux/bcm27xx/bcm2709/config-6.1 b/target/linux/bcm27xx/bcm2709/config-6.1 index ec2e7f3fa6..15bbaabd74 100644 --- a/target/linux/bcm27xx/bcm2709/config-6.1 +++ b/target/linux/bcm27xx/bcm2709/config-6.1 @@ -39,7 +39,6 @@ CONFIG_ASSOCIATIVE_ARRAY=y CONFIG_AUTO_ZRELADDR=y CONFIG_BCM2708_VCMEM=y CONFIG_BCM2711_THERMAL=y -CONFIG_BCM2835_DEVGPIOMEM=y CONFIG_BCM2835_MBOX=y CONFIG_BCM2835_POWER=y # CONFIG_BCM2835_SMI is not set @@ -186,7 +185,6 @@ CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CMDLINE=y -# CONFIG_FB_RPISENSE is not set CONFIG_FB_SIMPLE=y CONFIG_FIQ=y CONFIG_FIXED_PHY=y @@ -297,8 +295,6 @@ CONFIG_MDIO_DEVRES=y CONFIG_MEMFD_CREATE=y CONFIG_MEMORY_ISOLATION=y CONFIG_MFD_CORE=y -# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set -# CONFIG_MFD_RPISENSE_CORE is not set CONFIG_MFD_SYSCON=y CONFIG_MICROCHIP_PHY=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y @@ -332,6 +328,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_CONFIGFS=y @@ -374,7 +371,6 @@ CONFIG_PM_GENERIC_DOMAINS_SLEEP=y CONFIG_PM_OPP=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y -# CONFIG_PM_USERSPACE_AUTOSLEEP is not set CONFIG_POWER_SUPPLY=y CONFIG_PPS=y CONFIG_PREEMPT_NONE_BUILD=y @@ -387,6 +383,7 @@ CONFIG_PWM_SYSFS=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RAS=y CONFIG_RASPBERRYPI_FIRMWARE=y +CONFIG_RASPBERRYPI_GPIOMEM=y CONFIG_RASPBERRYPI_POWER=y CONFIG_RATIONAL=y # CONFIG_RAVE_SP_CORE is not set diff --git a/target/linux/bcm27xx/bcm2710/config-6.1 b/target/linux/bcm27xx/bcm2710/config-6.1 index b0abd49c7f..50b3f87d7d 100644 --- a/target/linux/bcm27xx/bcm2710/config-6.1 +++ b/target/linux/bcm27xx/bcm2710/config-6.1 @@ -60,7 +60,6 @@ CONFIG_ASSOCIATIVE_ARRAY=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y CONFIG_BCM2708_VCMEM=y # CONFIG_BCM2711_THERMAL is not set -CONFIG_BCM2835_DEVGPIOMEM=y CONFIG_BCM2835_MBOX=y CONFIG_BCM2835_POWER=y # CONFIG_BCM2835_SMI is not set @@ -152,7 +151,6 @@ CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_SHA1=y CONFIG_CRYPTO_LIB_SHA256=y CONFIG_CRYPTO_LIB_UTILS=y -# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_RNG_DEFAULT=y @@ -161,8 +159,6 @@ CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA256_ARM64=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_SHA512_ARM64=y -# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set -# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set CONFIG_CRYPTO_XTS=y CONFIG_DCACHE_WORD_ACCESS=y CONFIG_DEBUG_BUGVERBOSE=y @@ -195,7 +191,6 @@ CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CMDLINE=y -# CONFIG_FB_RPISENSE is not set CONFIG_FB_SIMPLE=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y @@ -299,8 +294,6 @@ CONFIG_MDIO_DEVRES=y CONFIG_MEMFD_CREATE=y CONFIG_MEMORY_ISOLATION=y CONFIG_MFD_CORE=y -# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set -# CONFIG_MFD_RPISENSE_CORE is not set CONFIG_MFD_SYSCON=y CONFIG_MICROCHIP_PHY=y CONFIG_MIGRATION=y @@ -332,6 +325,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_CONFIGFS=y @@ -368,7 +362,6 @@ CONFIG_PM_GENERIC_DOMAINS_SLEEP=y CONFIG_PM_OPP=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y -# CONFIG_PM_USERSPACE_AUTOSLEEP is not set CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y CONFIG_POWER_RESET=y CONFIG_POWER_SUPPLY=y @@ -382,6 +375,7 @@ CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RASPBERRYPI_FIRMWARE=y +CONFIG_RASPBERRYPI_GPIOMEM=y CONFIG_RASPBERRYPI_POWER=y CONFIG_RATIONAL=y # CONFIG_RAVE_SP_CORE is not set diff --git a/target/linux/bcm27xx/bcm2711/config-6.1 b/target/linux/bcm27xx/bcm2711/config-6.1 index ff88926e3d..0441305067 100644 --- a/target/linux/bcm27xx/bcm2711/config-6.1 +++ b/target/linux/bcm27xx/bcm2711/config-6.1 @@ -24,14 +24,8 @@ CONFIG_ARM64=y CONFIG_ARM64_4K_PAGES=y CONFIG_ARM64_CNP=y CONFIG_ARM64_EPAN=y -CONFIG_ARM64_ERRATUM_819472=y -CONFIG_ARM64_ERRATUM_824069=y -CONFIG_ARM64_ERRATUM_826319=y -CONFIG_ARM64_ERRATUM_827319=y -CONFIG_ARM64_ERRATUM_832075=y -CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_1319367=y CONFIG_ARM64_HW_AFDBM=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 @@ -60,7 +54,6 @@ CONFIG_ASSOCIATIVE_ARRAY=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y CONFIG_BCM2708_VCMEM=y CONFIG_BCM2711_THERMAL=y -CONFIG_BCM2835_DEVGPIOMEM=y CONFIG_BCM2835_MBOX=y CONFIG_BCM2835_POWER=y # CONFIG_BCM2835_SMI is not set @@ -156,7 +149,6 @@ CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_SHA1=y CONFIG_CRYPTO_LIB_SHA256=y CONFIG_CRYPTO_LIB_UTILS=y -# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_RNG_DEFAULT=y @@ -165,8 +157,6 @@ CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA256_ARM64=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_SHA512_ARM64=y -# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set -# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set CONFIG_CRYPTO_XTS=y CONFIG_DCACHE_WORD_ACCESS=y CONFIG_DEBUG_BUGVERBOSE=y @@ -200,7 +190,6 @@ CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CMDLINE=y -# CONFIG_FB_RPISENSE is not set CONFIG_FB_SIMPLE=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y @@ -306,8 +295,6 @@ CONFIG_MDIO_DEVRES=y CONFIG_MEMFD_CREATE=y CONFIG_MEMORY_ISOLATION=y CONFIG_MFD_CORE=y -# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set -# CONFIG_MFD_RPISENSE_CORE is not set CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y CONFIG_MMC=y @@ -339,6 +326,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_CONFIGFS=y @@ -378,7 +366,6 @@ CONFIG_PM_GENERIC_DOMAINS_SLEEP=y CONFIG_PM_OPP=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y -# CONFIG_PM_USERSPACE_AUTOSLEEP is not set CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y CONFIG_POWER_RESET=y CONFIG_POWER_SUPPLY=y @@ -395,6 +382,7 @@ CONFIG_QUEUED_SPINLOCKS=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RAS=y CONFIG_RASPBERRYPI_FIRMWARE=y +CONFIG_RASPBERRYPI_GPIOMEM=y CONFIG_RASPBERRYPI_POWER=y CONFIG_RATIONAL=y # CONFIG_RAVE_SP_CORE is not set diff --git a/target/linux/bcm27xx/bcm2712/config-6.1 b/target/linux/bcm27xx/bcm2712/config-6.1 new file mode 100644 index 0000000000..08445ffee2 --- /dev/null +++ b/target/linux/bcm27xx/bcm2712/config-6.1 @@ -0,0 +1,600 @@ +CONFIG_64BIT=y +# CONFIG_AIO is not set +CONFIG_APERTURE_HELPERS=y +CONFIG_ARCH_BCM=y +CONFIG_ARCH_BCM2835=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_BRCMSTB=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_CNP=y +CONFIG_ARM64_EPAN=y +CONFIG_ARM64_ERRATUM_1165522=y +CONFIG_ARM64_ERRATUM_1286807=y +CONFIG_ARM64_ERRATUM_1463225=y +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PAN=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PTR_AUTH=y +CONFIG_ARM64_PTR_AUTH_KERNEL=y +CONFIG_ARM64_SVE=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_BRCMSTB_AVS_CPUFREQ=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_RASPBERRYPI_CPUFREQ=y +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SMMU_V3 is not set +CONFIG_ARM_TIMER_SP804=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BCM2708_VCMEM=y +CONFIG_BCM2711_THERMAL=y +CONFIG_BCM2712_IOMMU=y +CONFIG_BCM2712_MIP=y +CONFIG_BCM2835_MBOX=y +CONFIG_BCM2835_POWER=y +CONFIG_BCM2835_SMI=y +CONFIG_BCM2835_SMI_DEV=m +CONFIG_BCM2835_THERMAL=y +CONFIG_BCM2835_VCHIQ=y +# CONFIG_BCM2835_VCHIQ_MMAL is not set +CONFIG_BCM2835_WDT=y +CONFIG_BCM7038_L1_IRQ=y +CONFIG_BCM7120_L2_IRQ=y +CONFIG_BCM7XXX_PHY=y +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_DEBUG is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_FALLBACK_SPROM=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +# CONFIG_BCMA_HOST_SOC is not set +CONFIG_BCMGENET=y +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BCM_VCIO=y +# CONFIG_BCM_VC_SM_CMA is not set +CONFIG_BCM_VIDEOCORE=y +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NVME=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BRCMSTB_DPFE=y +CONFIG_BRCMSTB_L2_IRQ=y +CONFIG_BRCMSTB_MEMC=y +CONFIG_BRCMSTB_PM=y +# CONFIG_BRCMSTB_THERMAL is not set +CONFIG_BRCM_CHAR_DRIVERS=y +CONFIG_BRCM_USB_PINMAP=y +CONFIG_BROADCOM_PHY=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLK_BCM2711_DVP=y +CONFIG_CLK_BCM2835=y +CONFIG_CLK_RASPBERRYPI=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMA=y +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_SIZE_MBYTES=5 +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_RP1=y +# CONFIG_COMMON_CLK_RP1_SDIO is not set +CONFIG_COMMON_CLK_XGENE=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CONTIG_ALLOC=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CRC16=y +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_BS=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA3_ARM64=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SHA512_ARM64=y +CONFIG_CRYPTO_SHA512_ARM64_CE=y +CONFIG_CRYPTO_SM3=y +CONFIG_CRYPTO_SM3_ARM64_CE=y +CONFIG_CRYPTO_SM4=y +CONFIG_CRYPTO_SM4_ARM64_CE=y +CONFIG_CRYPTO_SM4_ARM64_CE_BLK=y +CONFIG_CRYPTO_XTS=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DIMLIB=y +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2708=y +CONFIG_DMA_BCM2835=y +CONFIG_DMA_CMA=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DNOTIFY=y +CONFIG_DTC=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXTCON=y +CONFIG_F2FS_FS=y +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_CMDLINE=y +CONFIG_FB_SIMPLE=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FONT_8x16=y +CONFIG_FONT_8x8=y +CONFIG_FONT_SUPPORT=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FRAME_POINTER=y +CONFIG_FREEZER=y +CONFIG_FSL_ERRATUM_A008585=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_ALGS=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_INJECTION=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_BCM_VIRT=y +CONFIG_GPIO_BRCMSTB=y +CONFIG_GPIO_CDEV=y +# CONFIG_GPIO_FSM is not set +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_RASPBERRYPI_EXP=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +CONFIG_HOTPLUG_PCI_SHPC=y +CONFIG_HWMON=y +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_IPROC_RNG200=y +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_BCM2708 is not set +CONFIG_I2C_BCM2835=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_BRCMSTB=y +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INPUT=y +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_RASPBERRYPI_BUTTON=y +CONFIG_IOMMU_API=y +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_IOVA=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_DART is not set +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_KEYS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGER_ACTPWR=y +CONFIG_LEDS_TRIGGER_INPUT=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_MACB=y +CONFIG_MACB_PCI=y +CONFIG_MACB_USE_HWSTAMP=y +CONFIG_MAC_PARTITION=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +CONFIG_MDIO_BCM_UNIMAC=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEMFD_CREATE=y +CONFIG_MEMORY=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_MFD_CORE=y +CONFIG_MFD_RP1=y +CONFIG_MFD_SYSCON=y +CONFIG_MICROCHIP_PHY=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +# CONFIG_MMC_BCM2835 is not set +CONFIG_MMC_BCM2835_DMA=y +CONFIG_MMC_BCM2835_MMC=y +CONFIG_MMC_BCM2835_PIO_DMA_BARRIER=2 +CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_CQHCI=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_BRCMSTB=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_IPROC=y +CONFIG_MMC_SDHCI_OF_DWCMSHC=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SELFTESTS=y +CONFIG_NLS=y +CONFIG_NLS_ASCII=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVME_CORE=y +# CONFIG_NVME_HWMON is not set +# CONFIG_NVME_MULTIPATH is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_CONFIGFS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IOMMU=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEAER_INJECT=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +CONFIG_PCIEASPM_POWER_SUPERSAVE=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_BRCMSTB=y +CONFIG_PCIE_DPC=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_DW_PLAT=y +CONFIG_PCIE_DW_PLAT_HOST=y +CONFIG_PCIE_MICROCHIP_HOST=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_ECAM=y +CONFIG_PCI_HOST_COMMON=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_STUB=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_BRCM_SATA is not set +CONFIG_PHY_BRCM_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_BCM2712=y +CONFIG_PINCTRL_BCM2835=y +CONFIG_PINCTRL_RP1=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_OPP=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_BCM2835=y +CONFIG_PWM_BRCMSTB=y +CONFIG_PWM_RP1=y +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RASPBERRYPI_FIRMWARE=y +CONFIG_RASPBERRYPI_GPIOMEM=y +CONFIG_RASPBERRYPI_POWER=y +CONFIG_RATIONAL=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_RESET_BRCMSTB=y +CONFIG_RESET_BRCMSTB_RESCAL=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_RASPBERRYPI=y +CONFIG_RESET_SIMPLE=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +# CONFIG_RPIVID_MEM is not set +# CONFIG_RPI_POE_POWER is not set +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_BRCMSTB=y +CONFIG_RTC_DRV_RPI=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_PROC_FS is not set +CONFIG_SENSORS_RASPBERRYPI_HWMON=y +CONFIG_SENSORS_RP1_ADC=y +CONFIG_SERIAL_8250_BCM2835AUX=y +CONFIG_SERIAL_8250_BCM7271=y +# CONFIG_SERIAL_8250_DMA is not set +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=0 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +# CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SMSC_PHY=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BRCMSTB=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SRCU=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_TEXTSEARCH is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +# CONFIG_UACCE is not set +# CONFIG_UCLAMP_TASK is not set +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_BRCMSTB is not set +CONFIG_USB_COMMON=y +CONFIG_USB_DWCOTG=y +CONFIG_USB_GADGET=y +# CONFIG_USB_HCD_BCMA is not set +CONFIG_USB_PCI=y +CONFIG_USB_PHY=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_UAS=y +# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_VCHIQ_CDEV=y +CONFIG_VMAP_STACK=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZONE_DMA32=y diff --git a/target/linux/bcm27xx/bcm2712/target.mk b/target/linux/bcm27xx/bcm2712/target.mk new file mode 100644 index 0000000000..4fe9910351 --- /dev/null +++ b/target/linux/bcm27xx/bcm2712/target.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ARCH:=aarch64 +SUBTARGET:=bcm2712 +BOARDNAME:=BCM2712 boards (64 bit) +CPU_TYPE:=cortex-a76 +FEATURES+=pci pcie + +define Target/Description + Build firmware image for BCM2712 devices. + This firmware features a 64 bit kernel. +endef diff --git a/target/linux/bcm27xx/image/Makefile b/target/linux/bcm27xx/image/Makefile index ad79ac7d0c..e55a7b17b5 100644 --- a/target/linux/bcm27xx/image/Makefile +++ b/target/linux/bcm27xx/image/Makefile @@ -172,4 +172,22 @@ ifeq ($(SUBTARGET),bcm2711) TARGET_DEVICES += rpi-4 endif +define Device/rpi-5 + DEVICE_MODEL := 5 + KERNEL_IMG := kernel_2712.img + DEVICE_DTS := broadcom/bcm2712-rpi-5-b + SUPPORTED_DEVICES := raspberrypi,5-model-b + DEVICE_PACKAGES := \ + cypress-firmware-43455-sdio \ + brcmfmac-nvram-43455-sdio \ + kmod-brcmfmac wpad-basic-mbedtls \ + kmod-hwmon-pwmfan kmod-thermal \ + kmod-usb-dwc3 kmod-usb3 + IMAGE/sysupgrade.img.gz := boot-common | boot-2711 | sdcard-img | gzip | append-metadata + IMAGE/factory.img.gz := boot-common | boot-2711 | sdcard-img | gzip +endef +ifeq ($(SUBTARGET),bcm2712) + TARGET_DEVICES += rpi-5 +endif + $(eval $(call BuildImage)) diff --git a/target/linux/bcm27xx/image/config.txt b/target/linux/bcm27xx/image/config.txt index f8ca1bf2d4..db35d72ab7 100644 --- a/target/linux/bcm27xx/image/config.txt +++ b/target/linux/bcm27xx/image/config.txt @@ -4,7 +4,7 @@ ################################################################################ # For overclocking and various other settings, see: -# https://www.raspberrypi.org/documentation/configuration/config-txt/README.md +# https://www.raspberrypi.com/documentation/computers/config_txt.html ################################################################################ # OpenWrt config diff --git a/target/linux/bcm27xx/image/distroconfig.txt b/target/linux/bcm27xx/image/distroconfig.txt index 103c5d2e82..b09e5b8466 100644 --- a/target/linux/bcm27xx/image/distroconfig.txt +++ b/target/linux/bcm27xx/image/distroconfig.txt @@ -5,7 +5,7 @@ # Restore PL011 (ttyAMA0) to GPIOs 14 & 15, instead of Mini UART (ttyS0). # Mini UART is disabled by default unless "enable_uart=1" is specified, # which changes the core frequency to a fixed value and impacts performance. -# See https://www.raspberrypi.org/documentation/configuration/uart.md +# See https://www.raspberrypi.com/documentation/computers/configuration.html#mini-uart-and-cpu-core-frequency [pi0w] dtoverlay=disable-bt [pi3] diff --git a/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch b/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch index 178d0c514e..b64f2972c5 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch @@ -88,7 +88,7 @@ Signed-off-by: Maxime Ripard commit->event = kzalloc(sizeof(*commit->event), --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c -@@ -7743,6 +7743,19 @@ static int intel_atomic_commit(struct dr +@@ -7754,6 +7754,19 @@ static int intel_atomic_commit(struct dr state->base.legacy_cursor_update = false; } diff --git a/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch b/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch index 7304bf8bb6..bd2ccaa197 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch @@ -24,7 +24,7 @@ Signed-off-by: Phil Elwell --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c -@@ -2207,7 +2207,7 @@ mackey_and_ltk: +@@ -2214,7 +2214,7 @@ mackey_and_ltk: if (err) return SMP_UNSPECIFIED; @@ -33,7 +33,7 @@ Signed-off-by: Phil Elwell if (hcon->out) { sc_dhkey_check(smp); SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); -@@ -2222,9 +2222,6 @@ mackey_and_ltk: +@@ -2229,9 +2229,6 @@ mackey_and_ltk: confirm_hint = 0; confirm: diff --git a/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch index a74b2cd62f..09402fbc35 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch @@ -266,7 +266,7 @@ Signed-off-by: Phil Elwell static inline int mmc_blk_part_switch(struct mmc_card *card, unsigned int part_type); static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, -@@ -2998,6 +3005,8 @@ static int mmc_blk_probe(struct mmc_card +@@ -3000,6 +3007,8 @@ static int mmc_blk_probe(struct mmc_card { struct mmc_blk_data *md; int ret = 0; @@ -275,7 +275,7 @@ Signed-off-by: Phil Elwell /* * Check that the card supports the command class(es) we need. -@@ -3005,7 +3014,16 @@ static int mmc_blk_probe(struct mmc_card +@@ -3007,7 +3016,16 @@ static int mmc_blk_probe(struct mmc_card if (!(card->csd.cmdclass & CCC_BLOCK_READ)) return -ENODEV; @@ -293,7 +293,7 @@ Signed-off-by: Phil Elwell card->complete_wq = alloc_workqueue("mmc_complete", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); -@@ -3020,6 +3038,17 @@ static int mmc_blk_probe(struct mmc_card +@@ -3022,6 +3040,17 @@ static int mmc_blk_probe(struct mmc_card goto out_free; } diff --git a/target/linux/bcm27xx/patches-6.1/950-0146-sc16is7xx-Don-t-spin-if-no-data-received.patch b/target/linux/bcm27xx/patches-6.1/950-0146-sc16is7xx-Don-t-spin-if-no-data-received.patch deleted file mode 100644 index 30fcdb5218..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0146-sc16is7xx-Don-t-spin-if-no-data-received.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 1f9195cda30b320038cf94b4d14f85e58dd69d6d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 6 Nov 2018 12:57:48 +0000 -Subject: [PATCH] sc16is7xx: Don't spin if no data received - -See: https://github.com/raspberrypi/linux/issues/2676 - -Signed-off-by: Phil Elwell ---- - drivers/tty/serial/sc16is7xx.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/tty/serial/sc16is7xx.c -+++ b/drivers/tty/serial/sc16is7xx.c -@@ -783,6 +783,8 @@ static bool sc16is7xx_port_irq(struct sc - - if (rxlen) - sc16is7xx_handle_rx(port, rxlen, iir); -+ else -+ return false; - break; - /* CTSRTS interrupt comes only when CTS goes inactive */ - case SC16IS7XX_IIR_CTSRTS_SRC: diff --git a/target/linux/bcm27xx/patches-6.1/950-0149-Update-issue-templates-2736.patch b/target/linux/bcm27xx/patches-6.1/950-0149-Update-issue-templates-2736.patch deleted file mode 100644 index c394b48981..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0149-Update-issue-templates-2736.patch +++ /dev/null @@ -1,47 +0,0 @@ -From f1457e83cd211ef7c8c90e9a69d044366621c83f Mon Sep 17 00:00:00 2001 -From: James Hughes -Date: Fri, 2 Nov 2018 11:55:49 +0000 -Subject: [PATCH] Update issue templates (#2736) - ---- - .github/ISSUE_TEMPLATE/bug_report.md | 34 ++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md - ---- /dev/null -+++ b/.github/ISSUE_TEMPLATE/bug_report.md -@@ -0,0 +1,34 @@ -+--- -+name: Bug report -+about: Create a report to help us fix your issue -+ -+--- -+ -+**Is this the right place for my bug report?** -+This repository contains the Linux kernel used on the Raspberry Pi. If you believe that the issue you are seeing is kernel-related, this is the right place. If not, we have other repositories for the GPU firmware at [github.com/raspberrypi/firmware](https://github.com/raspberrypi/firmware) and Raspberry Pi userland applications at [github.com/raspberrypi/userland](https://github.com/raspberrypi/userland). If you have problems with the Raspbian distribution packages, report them in the [github.com/RPi-Distro/repo](https://github.com/RPi-Distro/repo). If you simply have a question, then [the Raspberry Pi forums](https://www.raspberrypi.org/forums) are the best place to ask it. -+ -+**Describe the bug** -+Add a clear and concise description of what you think the bug is. -+ -+**To reproduce** -+List the steps required to reproduce the issue. -+ -+**Expected behaviour** -+Add a clear and concise description of what you expected to happen. -+ -+**Actual behaviour** -+Add a clear and concise description of what actually happened. -+ -+**System** -+ Copy and paste the results of the raspinfo command in to this section. Alternatively, copy and paste a pastebin link, or add answers to the following questions: -+ -+* Which model of Raspberry Pi? e.g. Pi3B+, PiZeroW -+* Which OS and version (`cat /etc/rpi-issue`)? -+* Which firmware version (`vcgencmd version`)? -+* Which kernel version (`uname -a`)? -+ -+**Logs** -+If applicable, add the relevant output from `dmesg` or similar. -+ -+**Additional context** -+Add any other relevant context for the problem. diff --git a/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch b/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch index 4fc97de544..b805f1df30 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch @@ -18,7 +18,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -2657,7 +2657,7 @@ static void bcmgenet_init_tx_ring(struct +@@ -2659,7 +2659,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX); bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX); @@ -27,7 +27,7 @@ Signed-off-by: Phil Elwell /* Disable rate control for now */ bcmgenet_tdma_ring_writel(priv, index, flow_period_val, TDMA_FLOW_PERIOD); -@@ -4138,9 +4138,12 @@ static int bcmgenet_probe(struct platfor +@@ -4140,9 +4140,12 @@ static int bcmgenet_probe(struct platfor netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1); /* Set default coalescing parameters */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch b/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch index ba1baac7d0..da60efe07f 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch @@ -37,7 +37,7 @@ Signed-off-by: Phil Elwell static inline void bcmgenet_writel(u32 value, void __iomem *offset) { -@@ -2488,6 +2491,11 @@ static void reset_umac(struct bcmgenet_p +@@ -2490,6 +2493,11 @@ static void reset_umac(struct bcmgenet_p bcmgenet_rbuf_ctrl_set(priv, 0); udelay(10); diff --git a/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch index dc2e539f3a..89d7b4eea9 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch @@ -343,7 +343,7 @@ Signed-off-by: Naushir Patuck +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19279,6 +19279,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19281,6 +19281,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml F: drivers/media/i2c/imx412.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch index 8ba6f7e5fc..a7cf1bb1f2 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch @@ -177,7 +177,7 @@ Signed-off-by: Phil Elwell +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19287,6 +19287,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19289,6 +19289,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx477.yaml F: drivers/media/i2c/imx477.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch b/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch index e564af578e..03628b3e9f 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch @@ -132,7 +132,7 @@ Signed-off-by: David Plowman +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19284,6 +19284,7 @@ M: Raspberry Pi Kernel Maintenance --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -3633,6 +3633,7 @@ static int __spi_validate_bits_per_word( +@@ -3675,6 +3675,7 @@ static int spi_set_cs_timing(struct spi_ */ int spi_setup(struct spi_device *spi) { @@ -40,7 +40,7 @@ Signed-off-by: Phil Elwell unsigned bad_bits, ugly_bits; int status = 0; -@@ -3653,6 +3654,14 @@ int spi_setup(struct spi_device *spi) +@@ -3695,6 +3696,14 @@ int spi_setup(struct spi_device *spi) (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))) return -EINVAL; diff --git a/target/linux/bcm27xx/patches-6.1/950-0270-net-bcmgenet-Reset-RBUF-on-first-open.patch b/target/linux/bcm27xx/patches-6.1/950-0270-net-bcmgenet-Reset-RBUF-on-first-open.patch index 0c71db2d00..e21de6f79f 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0270-net-bcmgenet-Reset-RBUF-on-first-open.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0270-net-bcmgenet-Reset-RBUF-on-first-open.patch @@ -24,7 +24,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -3304,7 +3304,7 @@ static void bcmgenet_get_hw_addr(struct +@@ -3306,7 +3306,7 @@ static void bcmgenet_get_hw_addr(struct } /* Returns a reusable dma control register value */ @@ -33,7 +33,7 @@ Signed-off-by: Phil Elwell { unsigned int i; u32 reg; -@@ -3329,6 +3329,14 @@ static u32 bcmgenet_dma_disable(struct b +@@ -3331,6 +3331,14 @@ static u32 bcmgenet_dma_disable(struct b udelay(10); bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH); @@ -48,7 +48,7 @@ Signed-off-by: Phil Elwell return dma_ctrl; } -@@ -3392,8 +3400,8 @@ static int bcmgenet_open(struct net_devi +@@ -3394,8 +3402,8 @@ static int bcmgenet_open(struct net_devi bcmgenet_set_hw_addr(priv, dev->dev_addr); @@ -59,7 +59,7 @@ Signed-off-by: Phil Elwell /* Reinitialize TDMA and RDMA and SW housekeeping */ ret = bcmgenet_init_dma(priv); -@@ -4267,7 +4275,7 @@ static int bcmgenet_resume(struct device +@@ -4269,7 +4277,7 @@ static int bcmgenet_resume(struct device bcmgenet_hfb_create_rxnfc_filter(priv, rule); /* Disable RX/TX DMA and flush TX queues */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0368-Use-GitHubs-issue-form-for-bug-reports.patch b/target/linux/bcm27xx/patches-6.1/950-0368-Use-GitHubs-issue-form-for-bug-reports.patch deleted file mode 100644 index 7d08793af6..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0368-Use-GitHubs-issue-form-for-bug-reports.patch +++ /dev/null @@ -1,163 +0,0 @@ -From b9bf4e573a1e07ef999636cdb61f393df61cc447 Mon Sep 17 00:00:00 2001 -From: Andreas Blaesius -Date: Wed, 5 Jan 2022 20:38:39 +0100 -Subject: [PATCH] Use GitHubs issue form for bug reports - -Use GitHubs issue form for bug reports. - -- modern look -- user don't need to mess with given markdown parts while filling the issue template - -Setup config.yml for general questions and problems with the Raspbian distribution packages. ---- - .github/ISSUE_TEMPLATE/bug_report.md | 34 ---------- - .github/ISSUE_TEMPLATE/bug_report.yml | 91 +++++++++++++++++++++++++++ - .github/ISSUE_TEMPLATE/config.yml | 9 +++ - 3 files changed, 100 insertions(+), 34 deletions(-) - delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md - create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml - create mode 100644 .github/ISSUE_TEMPLATE/config.yml - ---- a/.github/ISSUE_TEMPLATE/bug_report.md -+++ /dev/null -@@ -1,34 +0,0 @@ ----- --name: Bug report --about: Create a report to help us fix your issue -- ----- -- --**Is this the right place for my bug report?** --This repository contains the Linux kernel used on the Raspberry Pi. If you believe that the issue you are seeing is kernel-related, this is the right place. If not, we have other repositories for the GPU firmware at [github.com/raspberrypi/firmware](https://github.com/raspberrypi/firmware) and Raspberry Pi userland applications at [github.com/raspberrypi/userland](https://github.com/raspberrypi/userland). If you have problems with the Raspbian distribution packages, report them in the [github.com/RPi-Distro/repo](https://github.com/RPi-Distro/repo). If you simply have a question, then [the Raspberry Pi forums](https://www.raspberrypi.org/forums) are the best place to ask it. -- --**Describe the bug** --Add a clear and concise description of what you think the bug is. -- --**To reproduce** --List the steps required to reproduce the issue. -- --**Expected behaviour** --Add a clear and concise description of what you expected to happen. -- --**Actual behaviour** --Add a clear and concise description of what actually happened. -- --**System** -- Copy and paste the results of the raspinfo command in to this section. Alternatively, copy and paste a pastebin link, or add answers to the following questions: -- --* Which model of Raspberry Pi? e.g. Pi3B+, PiZeroW --* Which OS and version (`cat /etc/rpi-issue`)? --* Which firmware version (`vcgencmd version`)? --* Which kernel version (`uname -a`)? -- --**Logs** --If applicable, add the relevant output from `dmesg` or similar. -- --**Additional context** --Add any other relevant context for the problem. ---- /dev/null -+++ b/.github/ISSUE_TEMPLATE/bug_report.yml -@@ -0,0 +1,91 @@ -+name: "Bug report" -+description: Create a report to help us fix your issue -+body: -+- type: markdown -+ attributes: -+ value: | -+ **Is this the right place for my bug report?** -+ This repository contains the Linux kernel used on the Raspberry Pi. -+ If you believe that the issue you are seeing is kernel-related, this is the right place. -+ If not, we have other repositories for the GPU firmware at [github.com/raspberrypi/firmware](https://github.com/raspberrypi/firmware) and Raspberry Pi userland applications at [github.com/raspberrypi/userland](https://github.com/raspberrypi/userland). -+ -+ If you have problems with the Raspbian distribution packages, report them in the [github.com/RPi-Distro/repo](https://github.com/RPi-Distro/repo). -+ If you simply have a question, then [the Raspberry Pi forums](https://www.raspberrypi.org/forums) are the best place to ask it. -+ -+- type: textarea -+ id: description -+ attributes: -+ label: Describe the bug -+ description: | -+ Add a clear and concise description of what you think the bug is. -+ validations: -+ required: true -+ -+- type: textarea -+ id: reproduce -+ attributes: -+ label: Steps to reproduce the behaviour -+ description: | -+ List the steps required to reproduce the issue. -+ validations: -+ required: true -+ -+- type: dropdown -+ id: model -+ attributes: -+ label: Device (s) -+ description: On which device you are facing the bug? -+ multiple: true -+ options: -+ - Raspberry Pi Zero -+ - Raspberry Pi Zero W / WH -+ - Raspberry Pi Zero 2 W -+ - Raspberry Pi 1 Mod. A -+ - Raspberry Pi 1 Mod. A+ -+ - Raspberry Pi 1 Mod. B -+ - Raspberry Pi 1 Mod. B+ -+ - Raspberry Pi 2 Mod. B -+ - Raspberry Pi 2 Mod. B v1.2 -+ - Raspberry Pi 3 Mod. A+ -+ - Raspberry Pi 3 Mod. B -+ - Raspberry Pi 3 Mod. B+ -+ - Raspberry Pi 4 Mod. B -+ - Raspberry Pi 400 -+ - Raspberry Pi CM1 -+ - Raspberry Pi CM3 -+ - Raspberry Pi CM3 Lite -+ - Raspberry Pi CM3+ -+ - Raspberry Pi CM3+ Lite -+ - Raspberry Pi CM4 -+ - Raspberry Pi CM4 Lite -+ - Other -+ validations: -+ required: true -+ -+- type: textarea -+ id: system -+ attributes: -+ label: System -+ description: | -+ Copy and paste the results of the raspinfo command in to this section. -+ Alternatively, copy and paste a pastebin link, or add answers to the following questions: -+ * Which OS and version (`cat /etc/rpi-issue`)? -+ * Which firmware version (`vcgencmd version`)? -+ * Which kernel version (`uname -a`)? -+ validations: -+ required: true -+ -+- type: textarea -+ id: logs -+ attributes: -+ label: Logs -+ description: | -+ If applicable, add the relevant output from `dmesg` or similar. -+ -+- type: textarea -+ id: additional -+ attributes: -+ label: Additional context -+ description: | -+ Add any other relevant context for the problem. -+ ---- /dev/null -+++ b/.github/ISSUE_TEMPLATE/config.yml -@@ -0,0 +1,9 @@ -+blank_issues_enabled: false -+contact_links: -+ - name: "⛔ Question" -+ url: https://www.raspberrypi.org/forums -+ about: "Please do not use GitHub for asking questions. If you simply have a question, then the Raspberry Pi forums are the best place to ask it. Thanks in advance for helping us keep the issue tracker clean!" -+ - name: "⛔ Problems with the Raspbian distribution packages" -+ url: https://github.com/RPi-Distro/repo -+ about: "If you have problems with the Raspbian distribution packages, please report them in the github.com/RPi-Distro/repo." -+ diff --git a/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch b/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch index de9378f79a..0335f00198 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch @@ -23,7 +23,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c -@@ -1928,7 +1928,7 @@ static void mmc_blk_mq_rw_recovery(struc +@@ -1930,7 +1930,7 @@ static void mmc_blk_mq_rw_recovery(struc return; } diff --git a/target/linux/bcm27xx/patches-6.1/950-0506-.github-Add-Github-Workflow-for-KUnit.patch b/target/linux/bcm27xx/patches-6.1/950-0506-.github-Add-Github-Workflow-for-KUnit.patch deleted file mode 100644 index bb3c3f160a..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0506-.github-Add-Github-Workflow-for-KUnit.patch +++ /dev/null @@ -1,74 +0,0 @@ -From d172f330087422b8f33ad5e0f60f903820e7b321 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 8 Dec 2022 13:17:42 +0100 -Subject: [PATCH] .github: Add Github Workflow for KUnit - -Now that we have some KUnit coverage, let's add a github actions file to -run them on each push or pull request. - -Signed-off-by: Maxime Ripard ---- - .github/workflows/kunit.yml | 57 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 57 insertions(+) - create mode 100644 .github/workflows/kunit.yml - ---- /dev/null -+++ b/.github/workflows/kunit.yml -@@ -0,0 +1,57 @@ -+name: KUnit Tests -+ -+on: -+ pull_request: -+ branches: [ "rpi-*"] -+ -+ push: -+ branches: [ "rpi-*"] -+ -+jobs: -+ core: -+ name: Generic DRM/KMS Unit Tests -+ runs-on: ubuntu-latest -+ -+ steps: -+ - uses: actions/checkout@v3 -+ -+ - name: Run Generic DRM Tests -+ run: | -+ ./tools/testing/kunit/kunit.py run \ -+ --kunitconfig=drivers/gpu/drm/tests -+ -+ vc4-arm: -+ name: VC4 Unit Tests on ARM -+ runs-on: ubuntu-latest -+ -+ steps: -+ - uses: actions/checkout@v3 -+ -+ - name: Install Dependencies -+ run: | -+ sudo apt-get update -+ sudo apt-get install -y gcc-arm-linux-gnueabihf qemu-system-arm -+ -+ - name: Run VC4 Tests -+ run: | -+ ./tools/testing/kunit/kunit.py run \ -+ --kunitconfig=drivers/gpu/drm/vc4/tests \ -+ --cross_compile=arm-linux-gnueabihf- --arch=arm -+ -+ vc4-arm64: -+ name: VC4 Unit Tests on ARM64 -+ runs-on: ubuntu-latest -+ -+ steps: -+ - uses: actions/checkout@v3 -+ -+ - name: Install Dependencies -+ run: | -+ sudo apt-get update -+ sudo apt-get install -y gcc-aarch64-linux-gnu qemu-system-arm -+ -+ - name: Run VC4 Tests -+ run: | -+ ./tools/testing/kunit/kunit.py run \ -+ --kunitconfig=drivers/gpu/drm/vc4/tests \ -+ --cross_compile=aarch64-linux-gnu- --arch=arm64 diff --git a/target/linux/bcm27xx/patches-6.1/950-0507-.github-workflows-Add-dtoverlaycheck-workflow.patch b/target/linux/bcm27xx/patches-6.1/950-0507-.github-workflows-Add-dtoverlaycheck-workflow.patch deleted file mode 100644 index 92a7b7edf4..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0507-.github-workflows-Add-dtoverlaycheck-workflow.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 4aec59014afc64d912502d70194a8823b0a6150a Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 6 Dec 2022 18:11:58 +0000 -Subject: [PATCH] .github/workflows: Add dtoverlaycheck workflow - -Signed-off-by: Dave Stevenson ---- - .github/workflows/dtoverlaycheck.yml | 48 ++++++++++++++++++++++++++++ - 1 file changed, 48 insertions(+) - create mode 100644 .github/workflows/dtoverlaycheck.yml - ---- /dev/null -+++ b/.github/workflows/dtoverlaycheck.yml -@@ -0,0 +1,48 @@ -+name: Pi dtoverlay checks -+ -+on: -+ pull_request: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ push: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ workflow_dispatch: -+ -+env: -+ UTILS_DIR: "${{github.workspace}}/utils" -+ -+jobs: -+ dtoverlaycheck: -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Install toolchain -+ run: | -+ sudo apt update -+ sudo apt-get install gcc-arm-linux-gnueabihf libfdt-dev device-tree-compiler -+ timeout-minutes: 10 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: overlaycheck -+ run: | -+ git clone https://github.com/raspberrypi/utils ${{env.UTILS_DIR}} -+ cd ${{env.UTILS_DIR}} -+ pwd -+ mkdir build -+ cd build -+ pwd -+ cmake .. -+ make -j4 -+ sudo make install -+ cd ${{github.workspace}} -+ pwd -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- dtbs -+ ${{env.UTILS_DIR}}/overlaycheck/overlaycheck diff --git a/target/linux/bcm27xx/patches-6.1/950-0508-.github-workflows-Create-workflow-to-CI-kernel-build.patch b/target/linux/bcm27xx/patches-6.1/950-0508-.github-workflows-Create-workflow-to-CI-kernel-build.patch deleted file mode 100644 index 101f6dafca..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0508-.github-workflows-Create-workflow-to-CI-kernel-build.patch +++ /dev/null @@ -1,285 +0,0 @@ -From baa2e8235af7143148d8799c5caed2a2eefd9107 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Fri, 11 Nov 2022 17:09:32 +0000 -Subject: [PATCH] .github/workflows: Create workflow to CI kernel - builds - -Builds the bcmrpi, bcm2709, bcm2711, and bcm2835 32 bit kernels, -and defconfig and bcm2711 64bit kernels, saving the artifacts for -7 days. - -Signed-off-by: Dave Stevenson ---- - .github/workflows/kernel-build.yml | 266 +++++++++++++++++++++++++++++ - 1 file changed, 266 insertions(+) - create mode 100644 .github/workflows/kernel-build.yml - ---- /dev/null -+++ b/.github/workflows/kernel-build.yml -@@ -0,0 +1,266 @@ -+name: Pi kernel build tests -+ -+on: -+ pull_request: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ push: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ workflow_dispatch: -+ -+env: -+ NUM_JOBS: 3 -+ -+jobs: -+ build-bcm2835: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/Image ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2835_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2835_build -+ path: bcm2835_build.tar -+ retention-days: 7 -+ -+ build-arm64: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-aarch64-linux-gnu -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf arm64_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: arm64_build -+ path: arm64_build.tar -+ retention-days: 7 -+ -+ build-bcmrpi: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcmrpi_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcmrpi_build -+ path: bcmrpi_build.tar -+ retention-days: 7 -+ -+ build-bcm2709: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -+ make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2709_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2709_build -+ path: bcm2709_build.tar -+ retention-days: 7 -+ -+ build-bcm2711: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2711_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2711_build -+ path: bcm2711_build.tar -+ retention-days: 7 -+ -+ build-bcm2711-arm64: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-aarch64-linux-gnu -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2711_arm64_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2711_arm64_build -+ path: bcm2711_arm64_build.tar -+ retention-days: 7 diff --git a/target/linux/bcm27xx/patches-6.1/950-0509-README-Add-README.md-with-CI-kernel-build-status-tag.patch b/target/linux/bcm27xx/patches-6.1/950-0509-README-Add-README.md-with-CI-kernel-build-status-tag.patch deleted file mode 100644 index 610efdc8a7..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0509-README-Add-README.md-with-CI-kernel-build-status-tag.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 81eebfa296eb1454cde3bf1cbd919f8b9eb6cf64 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 14 Nov 2022 17:14:15 +0000 -Subject: [PATCH] README: Add README.md with CI kernel build status - tags - -This is a copy of README with the tags added. - -You can not delete the file README as then checkpatch complains -you aren't in a kernel tree. - -Signed-off-by: Dave Stevenson ---- - README.md | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - create mode 100644 README.md - ---- /dev/null -+++ b/README.md -@@ -0,0 +1,30 @@ -+Linux kernel -+============ -+ -+There are several guides for kernel developers and users. These guides can -+be rendered in a number of formats, like HTML and PDF. Please read -+Documentation/admin-guide/README.rst first. -+ -+In order to build the documentation, use ``make htmldocs`` or -+``make pdfdocs``. The formatted documentation can also be read online at: -+ -+ https://www.kernel.org/doc/html/latest/ -+ -+There are various text files in the Documentation/ subdirectory, -+several of them using the Restructured Text markup notation. -+ -+Please read the Documentation/process/changes.rst file, as it contains the -+requirements for building and running the kernel, and information about -+the problems which may result by upgrading your kernel. -+ -+Build status for rpi-5.15.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -+ -+Build status for rpi-6.0.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -+ -+Build status for rpi-6.1.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) diff --git a/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch index a145f6c48f..cd9820fc9d 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch @@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell static inline void bcmgenet_writel(u32 value, void __iomem *offset) { -@@ -3438,6 +3441,17 @@ static int bcmgenet_open(struct net_devi +@@ -3440,6 +3443,17 @@ static int bcmgenet_open(struct net_devi bcmgenet_phy_pause_set(dev, priv->rx_pause, priv->tx_pause); diff --git a/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch b/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch index 2e6188af4b..6e51500140 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch @@ -138,7 +138,7 @@ Signed-off-by: Dave Stevenson +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19328,6 +19328,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19330,6 +19330,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx519.yaml F: drivers/media/i2c/imx519.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0538-.github-workflows-Set-warnings-as-errors-for-builds.patch b/target/linux/bcm27xx/patches-6.1/950-0538-.github-workflows-Set-warnings-as-errors-for-builds.patch deleted file mode 100644 index f880a637c1..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0538-.github-workflows-Set-warnings-as-errors-for-builds.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0a1c5c32cfe570a688a09c90ab16052fcb258342 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 13 Jan 2023 14:32:45 +0000 -Subject: [PATCH] .github/workflows: Set warnings-as-errors for builds - -To avoid code with build warnings being introduced into the tree, force -CONFIG_WERROR=y in the build workflow. - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -38,6 +38,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -78,6 +79,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -118,6 +120,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -158,6 +161,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -198,6 +202,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -248,6 +253,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install diff --git a/target/linux/bcm27xx/patches-6.1/950-0540-.github-workflows-Correct-kernel-builds-artifacts.patch b/target/linux/bcm27xx/patches-6.1/950-0540-.github-workflows-Correct-kernel-builds-artifacts.patch deleted file mode 100644 index 359efd5c85..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0540-.github-workflows-Correct-kernel-builds-artifacts.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 3e32a992acb7248183a3eb1d92503ac2d2eb2617 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 18 Jan 2023 09:34:31 +0000 -Subject: [PATCH] .github/workflows: Correct kernel builds artifacts - -Modify the kernel build workflow to create artifacts with the correct -names and structure, both as an example of what we expect and in case -anyone wants to use the output. - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 76 ++++++++++++++++-------------- - 1 file changed, 41 insertions(+), 35 deletions(-) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -37,14 +37,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays - make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/Image ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img - - - name: Tar build - run: tar -cvf bcm2835_build.tar -C ${{github.workspace}}/install . -@@ -78,14 +79,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img - - - name: Tar build - run: tar -cvf arm64_build.tar -C ${{github.workspace}}/install . -@@ -119,14 +121,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcmrpi_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img - - - name: Tar build - run: tar -cvf bcmrpi_build.tar -C ${{github.workspace}}/install . -@@ -160,14 +163,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7.img - - - name: Tar build - run: tar -cvf bcm2709_build.tar -C ${{github.workspace}}/install . -@@ -201,14 +205,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7l.img - - - name: Tar build - run: tar -cvf bcm2711_build.tar -C ${{github.workspace}}/install . -@@ -252,14 +257,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img - - - name: Tar build - run: tar -cvf bcm2711_arm64_build.tar -C ${{github.workspace}}/install . diff --git a/target/linux/bcm27xx/patches-6.1/950-0547-.github-workflows-Switch-to-a-matrix-build.patch b/target/linux/bcm27xx/patches-6.1/950-0547-.github-workflows-Switch-to-a-matrix-build.patch deleted file mode 100644 index 51f32be5a0..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0547-.github-workflows-Switch-to-a-matrix-build.patch +++ /dev/null @@ -1,333 +0,0 @@ -From 3ca614742a496b66a9b92ce6be05ff555fdfc2c2 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 23 Jan 2023 16:50:51 +0000 -Subject: [PATCH] .github/workflows: Switch to a matrix build - -Remove the per-build duplication by putting build parameters in a -matrix. - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 293 ++++++----------------------- - 1 file changed, 59 insertions(+), 234 deletions(-) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -15,177 +15,40 @@ env: - NUM_JOBS: 3 - - jobs: -- build-bcm2835: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img -- -- - name: Tar build -- run: tar -cvf bcm2835_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcm2835_build -- path: bcm2835_build.tar -- retention-days: 7 -- -- build-arm64: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-aarch64-linux-gnu -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img -- -- - name: Tar build -- run: tar -cvf arm64_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: arm64_build -- path: arm64_build.tar -- retention-days: 7 -- -- build-bcmrpi: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcmrpi_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img -- -- - name: Tar build -- run: tar -cvf bcmrpi_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcmrpi_build -- path: bcmrpi_build.tar -- retention-days: 7 -- -- build-bcm2709: -- -+ build: - runs-on: ubuntu-latest -+ strategy: -+ matrix: -+ include: -+ - name: bcm2835 -+ arch: arm -+ defconfig: bcm2835_defconfig -+ kernel: kernel - -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -+ - name: arm64 -+ arch: arm64 -+ defconfig: defconfig -+ kernel: kernel8 - -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7.img -+ - name: bcmrpi -+ arch: arm -+ defconfig: bcmrpi_defconfig -+ kernel: kernel - -- - name: Tar build -- run: tar -cvf bcm2709_build.tar -C ${{github.workspace}}/install . -+ - name: bcm2709 -+ arch: arm -+ defconfig: bcm2709_defconfig -+ kernel: kernel7 - -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcm2709_build -- path: bcm2709_build.tar -- retention-days: 7 -- -- build-bcm2711: -+ - name: bcm2711 -+ arch: arm -+ defconfig: bcm2711_defconfig -+ kernel: kernel7l - -- runs-on: ubuntu-latest -+ - name: bcm2711_arm64 -+ arch: arm64 -+ defconfig: bcm2711_defconfig -+ kernel: kernel8 - - steps: - - name: Update install -@@ -194,59 +57,11 @@ jobs: - - - name: Install toolchain - run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7l.img -- -- - name: Tar build -- run: tar -cvf bcm2711_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcm2711_build -- path: bcm2711_build.tar -- retention-days: 7 -- -- build-bcm2711-arm64: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-aarch64-linux-gnu -+ if [[ "${{matrix.arch}}" == "arm64" ]]; then -+ sudo apt-get install gcc-aarch64-linux-gnu; -+ else -+ sudo apt-get install gcc-arm-linux-gnueabihf; -+ fi - timeout-minutes: 5 - - - uses: actions/checkout@v3 -@@ -254,25 +69,35 @@ jobs: - fetch-depth: 1 - clean: true - -- - name: Build kernel -+ - name: Build kernel ${{matrix.name}} - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ export ARCH=${{matrix.arch}} -+ if [[ "$ARCH" == "arm64" ]]; then -+ export CROSS_COMPILE=aarch64-linux-gnu- -+ export DTS_SUBDIR=broadcom -+ export IMAGE=Image.gz -+ else -+ export CROSS_COMPILE=arm-linux-gnueabihf- -+ export DTS_SUBDIR= -+ export IMAGE=zImage -+ fi -+ make O=${{github.workspace}}/build ${{matrix.defconfig}} - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ make O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} $IMAGE modules dtbs - mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img -+ make O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/${ARCH}/boot/dts/${DTS_SUBDIR}/*.dtb ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/${ARCH}/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/${ARCH}/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/${ARCH}/boot/$IMAGE ${{github.workspace}}/install/boot/${{matrix.kernel}}.img - - - name: Tar build -- run: tar -cvf bcm2711_arm64_build.tar -C ${{github.workspace}}/install . -+ run: tar -cvf ${{matrix.name}}_build.tar -C ${{github.workspace}}/install . - - - name: Upload results - uses: actions/upload-artifact@v3 - with: -- name: bcm2711_arm64_build -- path: bcm2711_arm64_build.tar -+ name: ${{matrix.name}}_build -+ path: ${{matrix.name}}_build.tar - retention-days: 7 diff --git a/target/linux/bcm27xx/patches-6.1/950-0555-README.md-Replace-6.0-build-status-with-6.2.patch b/target/linux/bcm27xx/patches-6.1/950-0555-README.md-Replace-6.0-build-status-with-6.2.patch deleted file mode 100644 index 889ae948a8..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0555-README.md-Replace-6.0-build-status-with-6.2.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 1cc246c143210efe249978419b094b03bf2137e0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell <8911409+pelwell@users.noreply.github.com> -Date: Wed, 25 Jan 2023 10:19:52 +0000 -Subject: [PATCH] README.md: Replace 6.0 build status with 6.2 - -6.0 is EOL and 6.2 is heading towards release, so update the build status display accordingly. ---- - README.md | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/README.md -+++ b/README.md -@@ -21,10 +21,10 @@ Build status for rpi-5.15.y: - [![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) - [![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) - --Build status for rpi-6.0.y: --[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) --[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -- - Build status for rpi-6.1.y: - [![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) - [![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -+ -+Build status for rpi-6.2.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.2.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.2.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) diff --git a/target/linux/bcm27xx/patches-6.1/950-0556-.github-workflows-Retain-artifacts-for-90-days.patch b/target/linux/bcm27xx/patches-6.1/950-0556-.github-workflows-Retain-artifacts-for-90-days.patch deleted file mode 100644 index abc61e8b68..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0556-.github-workflows-Retain-artifacts-for-90-days.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 05a9a53de8785c82332081a5f44cc34dc9fa5f0c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 25 Jan 2023 15:01:43 +0000 -Subject: [PATCH] .github/workflows: Retain artifacts for 90 days - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -100,4 +100,4 @@ jobs: - with: - name: ${{matrix.name}}_build - path: ${{matrix.name}}_build.tar -- retention-days: 7 -+ retention-days: 90 diff --git a/target/linux/bcm27xx/patches-6.1/950-0583-workflows-We-all-love-checkpatch-so-add-it-to-the-CI.patch b/target/linux/bcm27xx/patches-6.1/950-0583-workflows-We-all-love-checkpatch-so-add-it-to-the-CI.patch deleted file mode 100644 index 109ae27c40..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0583-workflows-We-all-love-checkpatch-so-add-it-to-the-CI.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 6c110195b1f9b4e39676065d5973ecf603746862 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 8 Mar 2023 15:28:19 +0000 -Subject: [PATCH] workflows: We all love checkpatch, so add it to the - CI workflows - -This is currently running on defaults, so the --strict desired -for media drivers and similar won't be observed. That may be -possible to add later. - -Signed-off-by: Dave Stevenson ---- - .github/workflows/checkpatch.yml | 18 ++++++++++++++++++ - .github/workflows/ci_checkpatch.conf | 4 ++++ - 2 files changed, 22 insertions(+) - create mode 100644 .github/workflows/checkpatch.yml - create mode 100644 .github/workflows/ci_checkpatch.conf - ---- /dev/null -+++ b/.github/workflows/checkpatch.yml -@@ -0,0 +1,18 @@ -+name: Advisory checkpatch review -+on: [pull_request] -+ -+jobs: -+ review: -+ name: checkpatch review -+ runs-on: ubuntu-latest -+ steps: -+ - name: 'Calculate PR commits + 1' -+ run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> $GITHUB_ENV -+ - uses: actions/checkout@v3 -+ with: -+ ref: ${{ github.event.pull_request.head.sha }} -+ fetch-depth: ${{ env.PR_FETCH_DEPTH }} -+ - name: Copy checkpatch.conf -+ run: cp ${{github.workspace}}/.github/workflows/ci_checkpatch.conf ${{github.workspace}}/.checkpatch.conf -+ - name: Run checkpatch review -+ uses: webispy/checkpatch-action@v9 ---- /dev/null -+++ b/.github/workflows/ci_checkpatch.conf -@@ -0,0 +1,4 @@ -+--no-tree -+--ignore FILE_PATH_CHANGES -+--ignore GIT_COMMIT_ID -+--ignore SPDX_LICENSE_TAG diff --git a/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch b/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch index cfdeef78ab..4d6227a378 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch @@ -128,7 +128,7 @@ Signed-off-by: Sakari Ailus +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19270,6 +19270,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19272,6 +19272,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx290.txt F: drivers/media/i2c/imx290.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch index 94ddb850c3..de983ddb15 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Sakari Ailus --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19277,6 +19277,7 @@ L: linux-media@vger.kernel.org +@@ -19279,6 +19279,7 @@ L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/sony,imx296.yaml diff --git a/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch b/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch index 14a8a4a029..374069eca5 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch @@ -219,7 +219,7 @@ Signed-off-by: Sakari Ailus +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19267,7 +19267,7 @@ M: Manivannan Sadhasivam +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19342,7 +19342,7 @@ M: Raspberry Pi Kernel Maintenance -Date: Tue, 25 Apr 2023 11:49:41 +0100 -Subject: [PATCH] Bluetooth: hci_sync: Add fallback-bd-address prop - -The kernel Bluetooth framework understands that devices may not -be programmed with valid Bluetooth addresses. It also has the ability -to override a Bluetooth address with the value of the local-bd-address -DT property, but it ignores the validity of the existing address when -doing so. - -Add a new boolean property, fallback-bd-address, which indicates that -the given local-bd-address property should only be used if the device -does not already have a valid BDADDR. - -Signed-off-by: Phil Elwell ---- - net/bluetooth/hci_sync.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/net/bluetooth/hci_sync.c -+++ b/net/bluetooth/hci_sync.c -@@ -4630,6 +4630,7 @@ static const struct { - */ - static int hci_dev_setup_sync(struct hci_dev *hdev) - { -+ struct fwnode_handle *fwnode = dev_fwnode(hdev->dev.parent); - int ret = 0; - bool invalid_bdaddr; - size_t i; -@@ -4658,7 +4659,9 @@ static int hci_dev_setup_sync(struct hci - - if (!ret) { - if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) && -- !bacmp(&hdev->public_addr, BDADDR_ANY)) -+ !bacmp(&hdev->public_addr, BDADDR_ANY) && -+ (invalid_bdaddr || -+ !fwnode_property_present(fwnode, "fallback-bd-address"))) - hci_dev_get_bd_addr_from_property(hdev); - - if ((invalid_bdaddr || diff --git a/target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch b/target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch new file mode 100644 index 0000000000..276e51d2d9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch @@ -0,0 +1,306 @@ +From 3ad8e28669e0058e3cec482a47215e50e33f2574 Mon Sep 17 00:00:00 2001 +From: Vinay Varma +Date: Sun, 11 Jun 2023 23:45:03 +0800 +Subject: [PATCH] media: i2c: imx219: fix binning and rate_factor for 480p and + 1232p + +At a high FPS with RAW10, there is frame corruption for 480p because the +rate_factor of 2 is used with the normal 2x2 bining [1]. This commit +ties the rate_factor to the selected binning mode. For the 480p mode, +analog 2x2 binning mode with a rate_factor of 2 is always used. For the +1232p mode the normal 2x2 binning mode is used for RAW10 while analog +2x2 binning mode is used for RAW8. + +[1] https://github.com/raspberrypi/linux/issues/5493 + +Signed-off-by: Vinay Varma +--- + drivers/media/i2c/imx219.c | 143 ++++++++++++++++++++++++++----------- + 1 file changed, 100 insertions(+), 43 deletions(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -136,6 +136,18 @@ enum pad_types { + NUM_PADS + }; + ++enum binning_mode { ++ BINNING_NONE, ++ BINNING_DIGITAL_2x2, ++ BINNING_ANALOG_2x2, ++}; ++ ++enum binning_bit_depths { ++ BINNING_IDX_8_BIT, ++ BINNING_IDX_10_BIT, ++ BINNING_IDX_MAX ++}; ++ + struct imx219_reg { + u16 address; + u8 val; +@@ -162,11 +174,8 @@ struct imx219_mode { + /* Default register values */ + struct imx219_reg_list reg_list; + +- /* 2x2 binning is used */ +- bool binning; +- +- /* Relative pixel clock rate factor for the mode. */ +- unsigned int rate_factor; ++ /* binning mode based on format code */ ++ enum binning_mode binning[BINNING_IDX_MAX]; + }; + + static const struct imx219_reg imx219_common_regs[] = { +@@ -404,8 +413,10 @@ static const struct imx219_mode supporte + .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), + .regs = mode_3280x2464_regs, + }, +- .binning = false, +- .rate_factor = 1, ++ .binning = { ++ [BINNING_IDX_8_BIT] = BINNING_NONE, ++ [BINNING_IDX_10_BIT] = BINNING_NONE, ++ }, + }, + { + /* 1080P 30fps cropped */ +@@ -422,8 +433,10 @@ static const struct imx219_mode supporte + .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs), + .regs = mode_1920_1080_regs, + }, +- .binning = false, +- .rate_factor = 1, ++ .binning = { ++ [BINNING_IDX_8_BIT] = BINNING_NONE, ++ [BINNING_IDX_10_BIT] = BINNING_NONE, ++ }, + }, + { + /* 2x2 binned 30fps mode */ +@@ -440,8 +453,10 @@ static const struct imx219_mode supporte + .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs), + .regs = mode_1640_1232_regs, + }, +- .binning = true, +- .rate_factor = 1, ++ .binning = { ++ [BINNING_IDX_8_BIT] = BINNING_ANALOG_2x2, ++ [BINNING_IDX_10_BIT] = BINNING_DIGITAL_2x2, ++ }, + }, + { + /* 640x480 30fps mode */ +@@ -458,12 +473,10 @@ static const struct imx219_mode supporte + .num_of_regs = ARRAY_SIZE(mode_640_480_regs), + .regs = mode_640_480_regs, + }, +- .binning = true, +- /* +- * This mode uses a special 2x2 binning that doubles the +- * internal pixel clock rate. +- */ +- .rate_factor = 2, ++ .binning = { ++ [BINNING_IDX_8_BIT] = BINNING_ANALOG_2x2, ++ [BINNING_IDX_10_BIT] = BINNING_ANALOG_2x2, ++ }, + }, + }; + +@@ -652,12 +665,51 @@ static int imx219_open(struct v4l2_subde + return 0; + } + ++static int imx219_resolve_binning(struct imx219 *imx219, ++ enum binning_mode *binning) ++{ ++ switch (imx219->fmt.code) { ++ case MEDIA_BUS_FMT_SRGGB8_1X8: ++ case MEDIA_BUS_FMT_SGRBG8_1X8: ++ case MEDIA_BUS_FMT_SGBRG8_1X8: ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ *binning = imx219->mode->binning[BINNING_IDX_8_BIT]; ++ return 0; ++ ++ case MEDIA_BUS_FMT_SRGGB10_1X10: ++ case MEDIA_BUS_FMT_SGRBG10_1X10: ++ case MEDIA_BUS_FMT_SGBRG10_1X10: ++ case MEDIA_BUS_FMT_SBGGR10_1X10: ++ *binning = imx219->mode->binning[BINNING_IDX_10_BIT]; ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++static int imx219_get_rate_factor(struct imx219 *imx219) ++{ ++ enum binning_mode binning = BINNING_NONE; ++ int ret = imx219_resolve_binning(imx219, &binning); ++ ++ if (ret < 0) ++ return ret; ++ switch (binning) { ++ case BINNING_NONE: ++ case BINNING_DIGITAL_2x2: ++ return 1; ++ case BINNING_ANALOG_2x2: ++ return 2; ++ } ++ return -EINVAL; ++} ++ + static int imx219_set_ctrl(struct v4l2_ctrl *ctrl) + { + struct imx219 *imx219 = + container_of(ctrl->handler, struct imx219, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); + int ret; ++ int rate_factor; + + if (ctrl->id == V4L2_CID_VBLANK) { + int exposure_max, exposure_def; +@@ -679,6 +731,10 @@ static int imx219_set_ctrl(struct v4l2_c + if (pm_runtime_get_if_in_use(&client->dev) == 0) + return 0; + ++ rate_factor = imx219_get_rate_factor(imx219); ++ if (rate_factor < 0) ++ return rate_factor; ++ + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN, +@@ -687,7 +743,7 @@ static int imx219_set_ctrl(struct v4l2_c + case V4L2_CID_EXPOSURE: + ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE, + IMX219_REG_VALUE_16BIT, +- ctrl->val / imx219->mode->rate_factor); ++ ctrl->val / rate_factor); + break; + case V4L2_CID_DIGITAL_GAIN: + ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN, +@@ -708,7 +764,7 @@ static int imx219_set_ctrl(struct v4l2_c + ret = imx219_write_reg(imx219, IMX219_REG_VTS, + IMX219_REG_VALUE_16BIT, + (imx219->mode->height + ctrl->val) / +- imx219->mode->rate_factor); ++ rate_factor); + break; + case V4L2_CID_HBLANK: + ret = imx219_write_reg(imx219, IMX219_REG_HTS, +@@ -890,7 +946,7 @@ static int imx219_set_pad_format(struct + struct imx219 *imx219 = to_imx219(sd); + const struct imx219_mode *mode; + struct v4l2_mbus_framefmt *framefmt; +- int exposure_max, exposure_def, hblank, pixel_rate; ++ int exposure_max, exposure_def, hblank, pixel_rate, rate_factor; + unsigned int i; + + if (fmt->pad >= NUM_PADS) +@@ -924,6 +980,9 @@ static int imx219_set_pad_format(struct + + imx219->fmt = fmt->format; + imx219->mode = mode; ++ rate_factor = imx219_get_rate_factor(imx219); ++ if (rate_factor < 0) ++ return rate_factor; + /* Update limits and set FPS to default */ + __v4l2_ctrl_modify_range(imx219->vblank, + IMX219_VBLANK_MIN, +@@ -957,8 +1016,7 @@ static int imx219_set_pad_format(struct + __v4l2_ctrl_s_ctrl(imx219->hblank, hblank); + + /* Scale the pixel rate based on the mode specific factor */ +- pixel_rate = +- IMX219_PIXEL_RATE * imx219->mode->rate_factor; ++ pixel_rate = IMX219_PIXEL_RATE * rate_factor; + __v4l2_ctrl_modify_range(imx219->pixel_rate, pixel_rate, + pixel_rate, 1, pixel_rate); + } +@@ -1001,30 +1059,25 @@ static int imx219_set_framefmt(struct im + + static int imx219_set_binning(struct imx219 *imx219) + { +- if (!imx219->mode->binning) { ++ enum binning_mode binning = BINNING_NONE; ++ int ret = imx219_resolve_binning(imx219, &binning); ++ ++ if (ret < 0) ++ return ret; ++ switch (binning) { ++ case BINNING_NONE: + return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, + IMX219_REG_VALUE_16BIT, + IMX219_BINNING_NONE); +- } +- +- switch (imx219->fmt.code) { +- case MEDIA_BUS_FMT_SRGGB8_1X8: +- case MEDIA_BUS_FMT_SGRBG8_1X8: +- case MEDIA_BUS_FMT_SGBRG8_1X8: +- case MEDIA_BUS_FMT_SBGGR8_1X8: ++ case BINNING_DIGITAL_2x2: + return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, + IMX219_REG_VALUE_16BIT, +- IMX219_BINNING_2X2_ANALOG); +- +- case MEDIA_BUS_FMT_SRGGB10_1X10: +- case MEDIA_BUS_FMT_SGRBG10_1X10: +- case MEDIA_BUS_FMT_SGBRG10_1X10: +- case MEDIA_BUS_FMT_SBGGR10_1X10: ++ IMX219_BINNING_2X2); ++ case BINNING_ANALOG_2x2: + return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE, + IMX219_REG_VALUE_16BIT, +- IMX219_BINNING_2X2); ++ IMX219_BINNING_2X2_ANALOG); + } +- + return -EINVAL; + } + +@@ -1342,7 +1395,7 @@ static int imx219_init_controls(struct i + struct v4l2_ctrl_handler *ctrl_hdlr; + unsigned int height = imx219->mode->height; + struct v4l2_fwnode_device_properties props; +- int exposure_max, exposure_def, hblank, pixel_rate; ++ int exposure_max, exposure_def, hblank, pixel_rate, rate_factor; + int i, ret; + + ctrl_hdlr = &imx219->ctrl_handler; +@@ -1353,8 +1406,12 @@ static int imx219_init_controls(struct i + mutex_init(&imx219->mutex); + ctrl_hdlr->lock = &imx219->mutex; + ++ rate_factor = imx219_get_rate_factor(imx219); ++ if (rate_factor < 0) ++ return rate_factor; ++ + /* By default, PIXEL_RATE is read only */ +- pixel_rate = IMX219_PIXEL_RATE * imx219->mode->rate_factor; ++ pixel_rate = IMX219_PIXEL_RATE * rate_factor; + imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, + V4L2_CID_PIXEL_RATE, + pixel_rate, pixel_rate, +@@ -1576,6 +1633,9 @@ static int imx219_probe(struct i2c_clien + goto error_power_off; + usleep_range(100, 110); + ++ /* Initialize default format */ ++ imx219_set_default_format(imx219); ++ + ret = imx219_init_controls(imx219); + if (ret) + goto error_power_off; +@@ -1590,9 +1650,6 @@ static int imx219_probe(struct i2c_clien + imx219->pad[IMAGE_PAD].flags = MEDIA_PAD_FL_SOURCE; + imx219->pad[METADATA_PAD].flags = MEDIA_PAD_FL_SOURCE; + +- /* Initialize default format */ +- imx219_set_default_format(imx219); +- + ret = media_entity_pads_init(&imx219->sd.entity, NUM_PADS, imx219->pad); + if (ret) { + dev_err(dev, "failed to init entity pads: %d\n", ret); diff --git a/target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch b/target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch new file mode 100644 index 0000000000..c93ebf3e7e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch @@ -0,0 +1,28 @@ +From 52039b6ffb6e78c2f77319b167dceab9aa51d13f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 13 Jun 2023 16:12:54 +0100 +Subject: [PATCH] serial: sc16is7xx: Read modem line state at startup + +This patch sets the driver modem line state to the actual line state +at driver startup. + +See: https://github.com/raspberrypi/linux/issues/5501 + +Signed-off-by: Earl Schmidt +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/sc16is7xx.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -1221,6 +1221,9 @@ static int sc16is7xx_startup(struct uart + SC16IS7XX_IER_MSI_BIT; + sc16is7xx_port_write(port, SC16IS7XX_IER_REG, val); + ++ /* Initialize the Modem Control signals to current status */ ++ one->old_mctrl = sc16is7xx_get_hwmctrl(port); ++ + /* Enable modem status polling */ + spin_lock_irqsave(&port->lock, flags); + sc16is7xx_enable_ms(port); diff --git a/target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch b/target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch new file mode 100644 index 0000000000..6de340c2a9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch @@ -0,0 +1,79 @@ +From 6ef818eed60db70e9caf6bdf74cc1f9943994226 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Fri, 16 Jun 2023 16:24:19 +0100 +Subject: [PATCH] drivers: media: bcm2835_unicam: Improve frame sequence count + handling + +Ensure that the frame sequence counter is incremented only if a previous +frame start interrupt has occurred, or a frame start + frame end has +occurred simultaneously. + +This corresponds the sequence number with the actual number of frames +produced by the sensor, not the number of frame buffers dequeued back +to userland. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/bcm2835/bcm2835-unicam.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c ++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c +@@ -522,6 +522,7 @@ struct unicam_device { + /* subdevice async Notifier */ + struct v4l2_async_notifier notifier; + unsigned int sequence; ++ bool frame_started; + + /* ptr to sub device */ + struct v4l2_subdev *sensor; +@@ -914,6 +915,8 @@ static irqreturn_t unicam_isr(int irq, v + * buffer forever. + */ + if (fe) { ++ bool inc_seq = unicam->frame_started; ++ + /* + * Ensure we have swapped buffers already as we can't + * stop the peripheral. If no buffer is available, use a +@@ -949,11 +952,23 @@ static irqreturn_t unicam_isr(int irq, v + unicam_process_buffer_complete(node, sequence); + node->cur_frm = node->next_frm; + node->next_frm = NULL; ++ inc_seq = true; + } else { + node->cur_frm = node->next_frm; + } + } +- unicam->sequence++; ++ ++ /* ++ * Increment the sequence number conditionally on either a FS ++ * having already occurred, or in the FE + FS condition as ++ * caught in the FE handler above. This ensures the sequence ++ * number corresponds to the frames generated by the sensor, not ++ * the frames dequeued to userland. ++ */ ++ if (inc_seq) { ++ unicam->sequence++; ++ unicam->frame_started = false; ++ } + } + + if (ista & UNICAM_FSI) { +@@ -996,6 +1011,7 @@ static irqreturn_t unicam_isr(int irq, v + } + + unicam_queue_event_sof(unicam); ++ unicam->frame_started = true; + } + + /* +@@ -2600,6 +2616,7 @@ static int unicam_start_streaming(struct + vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); + } + ++ dev->frame_started = false; + unicam_start_rx(dev, buffer_addr); + + ret = v4l2_subdev_call(dev->sensor, video, s_stream, 1); diff --git a/target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch b/target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch new file mode 100644 index 0000000000..d8307f9009 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch @@ -0,0 +1,41 @@ +From bd8e59b0456870997fb917bcd3b3b696e78d4ac2 Mon Sep 17 00:00:00 2001 +From: 6by9 <6by9@users.noreply.github.com> +Date: Mon, 19 Jun 2023 16:02:36 +0100 +Subject: [PATCH] dtoverlays: Fix pitft[28|35] overlays for 6.1 driver change. + (#5508) + +The overlays configured both irq-gpio and an interrupts/ +interrupt-parent configuration for the stmpe MFD device. + +irq-gpio was reworked in 6.1 and has issues with the configuration +as provided. Removing it and using the interrupts/interrupt-parent +configuration works fine, so do that. + +See: https://forums.raspberrypi.com/viewtopic.php?t=351394 + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts | 1 - + arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts | 1 - + 2 files changed, 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts +@@ -68,7 +68,6 @@ + reg = <1>; + + spi-max-frequency = <500000>; +- irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ + interrupts = <24 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + interrupt-controller; +--- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts +@@ -68,7 +68,6 @@ + reg = <1>; + + spi-max-frequency = <500000>; +- irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ + interrupts = <24 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + interrupt-controller; diff --git a/target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch new file mode 100644 index 0000000000..2255efd988 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch @@ -0,0 +1,23 @@ +From 713a7ef9d73fca0f7fed122cb854d930b7a6ba5a Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 21 Jun 2023 08:45:02 +0100 +Subject: [PATCH] driver: media: i2c: imx477: Re-enable temperature sensor + +The temperature sensor enable register write got lost at some point. +Re-enable it. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx477.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -167,6 +167,7 @@ struct imx477_mode { + static const struct imx477_reg mode_common_regs[] = { + {0x0136, 0x18}, + {0x0137, 0x00}, ++ {0x0138, 0x01}, + {0xe000, 0x00}, + {0xe07a, 0x01}, + {0x0808, 0x02}, diff --git a/target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch b/target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch new file mode 100644 index 0000000000..43f63a1c63 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch @@ -0,0 +1,25 @@ +From d4c3133378b377ee519ea50247339cd61221fc47 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 21 Jun 2023 09:20:36 +0100 +Subject: [PATCH] overlays: allo-katana-dac-audio: Reduce I2C clock + +Higher speeds have been shown to cause data corruption on a Pi 4, +possibly due to clock-stretching. + +See: https://github.com/raspberrypi/linux/issues/5511 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts +@@ -30,6 +30,7 @@ + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; ++ clock-frequency = <50000>; + + allo-katana-codec@30 { + #sound-dai-cells = <0>; diff --git a/target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch new file mode 100644 index 0000000000..66c147837d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch @@ -0,0 +1,308 @@ +From 76c457e7e2920342637b1955fbaadf2aae282f05 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 23 Jun 2023 09:48:59 +0100 +Subject: [PATCH] overlays: jedec-spi-nor: Add speed parameter + +Add a speed parameter to the jedec-spi-nor overlay to allow much +faster accesses, taking the opportunity to simplify the internals. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 8 +- + .../dts/overlays/jedec-spi-nor-overlay.dts | 245 +++--------------- + 2 files changed, 41 insertions(+), 212 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2557,9 +2557,11 @@ Name: jedec-spi-nor + Info: Adds support for JEDEC-compliant SPI NOR flash devices. (Note: The + "jedec,spi-nor" kernel driver was formerly known as "m25p80".) + Load: dtoverlay=jedec-spi-nor,= +-Params: flash-spi- Enables flash device on SPI, CS#. +- flash-fastr-spi- Enables flash device with fast read capability +- on SPI, CS#. ++Params: spi- Enable flash device on SPI, CS# ++ fastr Add fast read capability to the flash device ++ speed Maximum SPI frequency (Hz) ++ flash-spi- Same as spi- (deprecated) ++ flash-fastr-spi- Same as spi->m>,fastr (deprecated) + + + Name: justboom-both +--- a/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts ++++ b/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts +@@ -3,6 +3,7 @@ + // dtparams: + // flash-spi- - Enables flash device on SPI, CS#. + // flash-fastr-spi- - Enables flash device with fast read capability on SPI, CS#. ++// speed - Set the SPI clock speed in Hz + // + // If devices are present on SPI1 or SPI2, those interfaces must be enabled with one of the spi1-1/2/3cs and/or spi2-1/2/3cs overlays. + // +@@ -79,50 +80,23 @@ + }; + }; + +- // enable flash on spi0.0 ++ // Enable fast read for device ++ // Use default active low interrupt signalling. + fragment@8 { +- target = <&spi0>; ++ target = <&spi_nor>; + __dormant__ { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_00: spi_nor@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <0>; +- spi-max-frequency = <500000>; +- }; ++ m25p,fast-read; + }; + }; + +- // enable flash on spi0.1 +- fragment@9 { ++ payload: fragment@100 { + target = <&spi0>; +- __dormant__ { ++ __overlay__ { + status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_01: spi_nor@1 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <1>; +- spi-max-frequency = <500000>; +- }; +- }; +- }; ++ #address-cells = <1>; ++ #size-cells = <0>; + +- // enable flash on spi1.0 +- fragment@10 { +- target = <&spi1>; +- __dormant__ { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_10: spi_nor@0 { +- #address-cells = <1>; +- #size-cells = <1>; ++ spi_nor: spi_nor@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <500000>; +@@ -130,180 +104,33 @@ + }; + }; + +- // enable flash on spi1.1 +- fragment@11 { +- target = <&spi1>; +- __dormant__ { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_11: spi_nor@1 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <1>; +- spi-max-frequency = <500000>; +- }; +- }; +- }; +- +- // enable flash on spi1.2 +- fragment@12 { +- target = <&spi1>; +- __dormant__ { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_12: spi_nor@2 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <2>; +- spi-max-frequency = <500000>; +- }; +- }; +- }; +- +- // enable flash on spi2.0 +- fragment@13 { +- target = <&spi2>; +- __dormant__ { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_20: spi_nor@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <0>; +- spi-max-frequency = <500000>; +- }; +- }; +- }; +- +- // enable flash on spi2.1 +- fragment@14 { +- target = <&spi2>; +- __dormant__ { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_21: spi_nor@1 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <1>; +- spi-max-frequency = <500000>; +- }; +- }; +- }; +- +- // enable flash on spi2.2 +- fragment@15 { +- target = <&spi2>; +- __dormant__ { +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- spi_nor_22: spi_nor@2 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <2>; +- spi-max-frequency = <500000>; +- }; +- }; +- }; +- +- // Enable fast read for device on spi0.0. +- // Use default active low interrupt signalling. +- fragment@16 { +- target = <&spi_nor_00>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- +- // Enable fast read for device on spi0.1. +- // Use default active low interrupt signalling. +- fragment@17 { +- target = <&spi_nor_01>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- +- // Enable fast read for device on spi1.0. +- // Use default active low interrupt signalling. +- fragment@18 { +- target = <&spi_nor_10>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- +- // Enable fast read for device on spi1.1. +- // Use default active low interrupt signalling. +- fragment@19 { +- target = <&spi_nor_11>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- +- // Enable fast read for device on spi1.2. +- // Use default active low interrupt signalling. +- fragment@20 { +- target = <&spi_nor_12>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- +- // Enable fast read for device on spi2.0. +- // Use default active low interrupt signalling. +- fragment@21 { +- target = <&spi_nor_20>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- +- // Enable fast read for device on spi2.1. +- // Use default active low interrupt signalling. +- fragment@22 { +- target = <&spi_nor_21>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- +- // Enable fast read for device on spi2.2. +- // Use default active low interrupt signalling. +- fragment@23 { +- target = <&spi_nor_22>; +- __dormant__ { +- m25p,fast-read; +- }; +- }; +- + __overrides__ { +- flash-spi0-0 = <0>,"+0+8"; +- flash-spi0-1 = <0>,"+1+9"; +- flash-spi1-0 = <0>,"+2+10"; +- flash-spi1-1 = <0>,"+3+11"; +- flash-spi1-2 = <0>,"+4+12"; +- flash-spi2-0 = <0>,"+5+13"; +- flash-spi2-1 = <0>,"+6+14"; +- flash-spi2-2 = <0>,"+7+15"; +- flash-fastr-spi0-0 = <0>,"+0+8+16"; +- flash-fastr-spi0-1 = <0>,"+1+9+17"; +- flash-fastr-spi1-0 = <0>,"+2+10+18"; +- flash-fastr-spi1-1 = <0>,"+3+11+19"; +- flash-fastr-spi1-2 = <0>,"+4+12+20"; +- flash-fastr-spi2-0 = <0>,"+5+13+21"; +- flash-fastr-spi2-1 = <0>,"+6+14+22"; +- flash-fastr-spi2-2 = <0>,"+7+15+23"; ++ spi0-0 = <0>,"+0", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=0"; ++ spi0-1 = <0>,"+1", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=1"; ++ spi1-0 = <0>,"+2", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=0"; ++ spi1-1 = <0>,"+3", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=1"; ++ spi1-2 = <0>,"+4", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=2"; ++ spi2-0 = <0>,"+5", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=0"; ++ spi2-1 = <0>,"+6", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=1"; ++ spi2-2 = <0>,"+7", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=2"; ++ flash-spi0-0 = <0>,"+0", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=0"; ++ flash-spi0-1 = <0>,"+1", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=1"; ++ flash-spi1-0 = <0>,"+2", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=0"; ++ flash-spi1-1 = <0>,"+3", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=1"; ++ flash-spi1-2 = <0>,"+4", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=2"; ++ flash-spi2-0 = <0>,"+5", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=0"; ++ flash-spi2-1 = <0>,"+6", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=1"; ++ flash-spi2-2 = <0>,"+7", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=2"; ++ flash-fastr-spi0-0 = <0>,"+0+8", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=0"; ++ flash-fastr-spi0-1 = <0>,"+1+8", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=1"; ++ flash-fastr-spi1-0 = <0>,"+2+8", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=0"; ++ flash-fastr-spi1-1 = <0>,"+3+8", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=1"; ++ flash-fastr-spi1-2 = <0>,"+4+8", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=2"; ++ flash-fastr-spi2-0 = <0>,"+5+8", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=0"; ++ flash-fastr-spi2-1 = <0>,"+6+8", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=1"; ++ flash-fastr-spi2-2 = <0>,"+7+8", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=2"; ++ fastr = <0>,"+8"; ++ speed = <&spi_nor>, "spi-max-frequency:0"; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch b/target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch new file mode 100644 index 0000000000..a35e7f4d1b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch @@ -0,0 +1,137 @@ +From e866f9fc7c6dd6af1e74ce6fa50db9ba21acae5e Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sat, 24 Jun 2023 18:52:16 +0200 +Subject: [PATCH] ALSA: pcm: fix ELD constraints for (E)AC3, DTS(-HD) and MLP + formats + +commit 04b49b90caeed0b5544ff616d654900d27d403b6 upstream. + +The SADs of compressed formats contain the channel and sample rate +info of the audio data inside the compressed stream, but when +building constraints we must use the rates and channels used to +transport the compressed streams. + +eg 48kHz 6ch EAC3 needs to be transmitted as a 2ch 192kHz stream. + +This patch fixes the constraints for the common AC3 and DTS formats, +the constraints for the less common MPEG, DSD etc formats are copied +directly from the info in the SADs as before as I don't have the specs +and equipment to test those. + +Signed-off-by: Matthias Reichl +Link: https://lore.kernel.org/r/20230624165216.5719-1-hias@horus.com +Signed-off-by: Takashi Iwai +--- + sound/core/pcm_drm_eld.c | 73 ++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 70 insertions(+), 3 deletions(-) + +--- a/sound/core/pcm_drm_eld.c ++++ b/sound/core/pcm_drm_eld.c +@@ -2,11 +2,25 @@ + /* + * PCM DRM helpers + */ ++#include + #include ++#include + #include + #include + #include + ++#define SAD0_CHANNELS_MASK GENMASK(2, 0) /* max number of channels - 1 */ ++#define SAD0_FORMAT_MASK GENMASK(6, 3) /* audio format */ ++ ++#define SAD1_RATE_MASK GENMASK(6, 0) /* bitfield of supported rates */ ++#define SAD1_RATE_32000_MASK BIT(0) ++#define SAD1_RATE_44100_MASK BIT(1) ++#define SAD1_RATE_48000_MASK BIT(2) ++#define SAD1_RATE_88200_MASK BIT(3) ++#define SAD1_RATE_96000_MASK BIT(4) ++#define SAD1_RATE_176400_MASK BIT(5) ++#define SAD1_RATE_192000_MASK BIT(6) ++ + static const unsigned int eld_rates[] = { + 32000, + 44100, +@@ -17,9 +31,62 @@ static const unsigned int eld_rates[] = + 192000, + }; + ++static unsigned int map_rate_families(const u8 *sad, ++ unsigned int mask_32000, ++ unsigned int mask_44100, ++ unsigned int mask_48000) ++{ ++ unsigned int rate_mask = 0; ++ ++ if (sad[1] & SAD1_RATE_32000_MASK) ++ rate_mask |= mask_32000; ++ if (sad[1] & (SAD1_RATE_44100_MASK | SAD1_RATE_88200_MASK | SAD1_RATE_176400_MASK)) ++ rate_mask |= mask_44100; ++ if (sad[1] & (SAD1_RATE_48000_MASK | SAD1_RATE_96000_MASK | SAD1_RATE_192000_MASK)) ++ rate_mask |= mask_48000; ++ return rate_mask; ++} ++ ++static unsigned int sad_rate_mask(const u8 *sad) ++{ ++ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) { ++ case HDMI_AUDIO_CODING_TYPE_PCM: ++ return sad[1] & SAD1_RATE_MASK; ++ case HDMI_AUDIO_CODING_TYPE_AC3: ++ case HDMI_AUDIO_CODING_TYPE_DTS: ++ return map_rate_families(sad, ++ SAD1_RATE_32000_MASK, ++ SAD1_RATE_44100_MASK, ++ SAD1_RATE_48000_MASK); ++ case HDMI_AUDIO_CODING_TYPE_EAC3: ++ case HDMI_AUDIO_CODING_TYPE_DTS_HD: ++ case HDMI_AUDIO_CODING_TYPE_MLP: ++ return map_rate_families(sad, ++ 0, ++ SAD1_RATE_176400_MASK, ++ SAD1_RATE_192000_MASK); ++ default: ++ /* TODO adjust for other compressed formats as well */ ++ return sad[1] & SAD1_RATE_MASK; ++ } ++} ++ + static unsigned int sad_max_channels(const u8 *sad) + { +- return 1 + (sad[0] & 7); ++ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) { ++ case HDMI_AUDIO_CODING_TYPE_PCM: ++ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]); ++ case HDMI_AUDIO_CODING_TYPE_AC3: ++ case HDMI_AUDIO_CODING_TYPE_DTS: ++ case HDMI_AUDIO_CODING_TYPE_EAC3: ++ return 2; ++ case HDMI_AUDIO_CODING_TYPE_DTS_HD: ++ case HDMI_AUDIO_CODING_TYPE_MLP: ++ return 8; ++ default: ++ /* TODO adjust for other compressed formats as well */ ++ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]); ++ } + } + + static int eld_limit_rates(struct snd_pcm_hw_params *params, +@@ -42,7 +109,7 @@ static int eld_limit_rates(struct snd_pc + * requested number of channels. + */ + if (c->min <= max_channels) +- rate_mask |= sad[1]; ++ rate_mask |= sad_rate_mask(sad); + } + } + +@@ -70,7 +137,7 @@ static int eld_limit_channels(struct snd + rate_mask |= BIT(i); + + for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) +- if (rate_mask & sad[1]) ++ if (rate_mask & sad_rate_mask(sad)) + t.max = max(t.max, sad_max_channels(sad)); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch b/target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch new file mode 100644 index 0000000000..31a351a4e8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch @@ -0,0 +1,86 @@ +From 3f388718331b5ce2acd34730448db001759868aa Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sat, 24 Jun 2023 18:52:32 +0200 +Subject: [PATCH] ASoC: hdmi-codec: fix channel info for compressed formats + +commit 4e0871333661d2ec0ed3dc00a945c2160eccae77 upstream. + +According to CTA 861 the channel/speaker allocation info in the +audio infoframe only applies to uncompressed (PCM) audio streams. + +The channel count info should indicate the number of channels +in the transmitted audio, which usually won't match the number of +channels used to transmit the compressed bitstream. + +Some devices (eg some Sony TVs) will refuse to decode compressed +audio if these values are not set correctly. + +To fix this we can simply set the channel count to 0 (which means +"refer to stream header") and set the channel/speaker allocation to 0 +as well (which would mean stereo FL/FR for PCM, a safe value all sinks +will support) when transmitting compressed audio. + +Signed-off-by: Matthias Reichl +Link: https://lore.kernel.org/r/20230624165232.5751-1-hias@horus.com +Signed-off-by: Takashi Iwai +--- + sound/soc/codecs/hdmi-codec.c | 36 +++++++++++++++++++++++------------ + 1 file changed, 24 insertions(+), 12 deletions(-) + +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -484,31 +484,43 @@ static int hdmi_codec_fill_codec_params( + struct hdmi_codec_params *hp) + { + struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); +- int idx; ++ int idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; ++ u8 ca_id = 0; ++ bool pcm_audio = !(hcp->iec_status[0] & IEC958_AES0_NONAUDIO); ++ ++ if (pcm_audio) { ++ /* Select a channel allocation that matches with ELD and pcm channels */ ++ idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels); ++ ++ if (idx < 0) { ++ dev_err(dai->dev, "Not able to map channels to speakers (%d)\n", ++ idx); ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; ++ return idx; ++ } + +- /* Select a channel allocation that matches with ELD and pcm channels */ +- idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels); +- if (idx < 0) { +- dev_err(dai->dev, "Not able to map channels to speakers (%d)\n", +- idx); +- hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; +- return idx; ++ ca_id = hdmi_codec_channel_alloc[idx].ca_id; + } + + memset(hp, 0, sizeof(*hp)); + + hdmi_audio_infoframe_init(&hp->cea); +- hp->cea.channels = channels; ++ ++ if (pcm_audio) ++ hp->cea.channels = channels; ++ else ++ hp->cea.channels = 0; ++ + hp->cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; + hp->cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; + hp->cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; +- hp->cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id; ++ hp->cea.channel_allocation = ca_id; + + hp->sample_width = sample_width; + hp->sample_rate = sample_rate; + hp->channels = channels; + +- hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id; ++ hcp->chmap_idx = idx; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch b/target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch new file mode 100644 index 0000000000..a423b8061b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch @@ -0,0 +1,44 @@ +From 9c5a7f04cab6b020389d7c5af155b1ee7f46537d Mon Sep 17 00:00:00 2001 +From: Lee Jackson +Date: Thu, 4 May 2023 11:14:04 +0800 +Subject: [PATCH] media: i2c: arducam_64mp: Modify the line length of 1280x720 + resolution + +Arducam 64MP has specific requirements for the line length, and if these +conditions are not met, the camera will not function properly. Under the +previous configuration, once a stream off operation is performed, the +camera will not output any data, even if a stream on operation is +performed. This prevents us from switching from 1280x720 to another +resolution. + +Signed-off-by: Lee Jackson +--- + drivers/media/i2c/arducam_64mp.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/media/i2c/arducam_64mp.c ++++ b/drivers/media/i2c/arducam_64mp.c +@@ -1063,10 +1063,10 @@ static const struct arducam_64mp_reg mod + + /* 720p 120fps mode */ + static const struct arducam_64mp_reg mode_1280x720_regs[] = { +- {0x0342, 0x1d}, +- {0x0343, 0xc4}, +- {0x0340, 0x03}, +- {0x0341, 0xd8}, ++ {0x0342, 0x1b}, ++ {0x0343, 0x08}, ++ {0x0340, 0x04}, ++ {0x0341, 0x3b}, + {0x0344, 0x08}, + {0x0345, 0x10}, + {0x0346, 0x07}, +@@ -1209,7 +1209,7 @@ static const struct arducam_64mp_mode su + }, { + .width = 1280, + .height = 720, +- .line_length_pix = 0x1dc4, ++ .line_length_pix = 0x1b08, + .crop = { + .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT + 2064, + .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP + 2032, diff --git a/target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch b/target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch new file mode 100644 index 0000000000..475ae634ad --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch @@ -0,0 +1,105 @@ +From 7b3d0124c5cf462d5be0b0d4e558002b74750911 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +Date: Fri, 5 May 2023 14:36:15 +0800 +Subject: [PATCH] media: i2c: arducam_64mp: Add 8000x6000 resolution + +Added 8000x6000 10-bit (cropped) @ 3fps mode for Arducam 64MP + +Signed-off-by: Lee Jackson +--- + drivers/media/i2c/arducam_64mp.c | 77 ++++++++++++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + +--- a/drivers/media/i2c/arducam_64mp.c ++++ b/drivers/media/i2c/arducam_64mp.c +@@ -849,6 +849,65 @@ static const struct arducam_64mp_reg mod + {0x020f, 0x00}, + }; + ++/* 48 mpix 3.0fps */ ++static const struct arducam_64mp_reg mode_8000x6000_regs[] = { ++ {0x0342, 0xb6}, ++ {0x0343, 0xb2}, ++ {0x0340, 0x19}, ++ {0x0341, 0x0e}, ++ {0x0344, 0x02}, ++ {0x0345, 0x70}, ++ {0x0346, 0x01}, ++ {0x0347, 0xd8}, ++ {0x0348, 0x21}, ++ {0x0349, 0xaf}, ++ {0x034a, 0x19}, ++ {0x034b, 0x47}, ++ {0x0900, 0x00}, ++ {0x0901, 0x11}, ++ {0x0902, 0x0a}, ++ {0x30d8, 0x00}, ++ {0x3200, 0x01}, ++ {0x3201, 0x01}, ++ {0x0408, 0x00}, ++ {0x0409, 0x00}, ++ {0x040a, 0x00}, ++ {0x040b, 0x00}, ++ {0x040c, 0x1f}, ++ {0x040d, 0x40}, ++ {0x040e, 0x17}, ++ {0x040f, 0x70}, ++ {0x034c, 0x1f}, ++ {0x034d, 0x40}, ++ {0x034e, 0x17}, ++ {0x034f, 0x70}, ++ {0x30d9, 0x01}, ++ {0x32d5, 0x01}, ++ {0x32d6, 0x00}, ++ {0x401e, 0x00}, ++ {0x40b8, 0x04}, ++ {0x40b9, 0x20}, ++ {0x40bc, 0x02}, ++ {0x40bd, 0x58}, ++ {0x40be, 0x02}, ++ {0x40bf, 0x58}, ++ {0x41a4, 0x00}, ++ {0x5a09, 0x01}, ++ {0x5a17, 0x01}, ++ {0x5a25, 0x01}, ++ {0x5a33, 0x01}, ++ {0x98d7, 0x14}, ++ {0x98d8, 0x14}, ++ {0x98d9, 0x00}, ++ {0x99c4, 0x00}, ++ {0x0202, 0x03}, ++ {0x0203, 0xe8}, ++ {0x0204, 0x00}, ++ {0x0205, 0x00}, ++ {0x020e, 0x01}, ++ {0x020f, 0x00}, ++}; ++ + /* 16 mpix 10fps */ + static const struct arducam_64mp_reg mode_4624x3472_regs[] = { + {0x0342, 0x63}, +@@ -1135,6 +1194,24 @@ static const struct arducam_64mp_mode su + .regs = mode_9152x6944_regs, + } + }, { ++ .width = 8000, ++ .height = 6000, ++ .line_length_pix = 0xb6b2, ++ .crop = { ++ .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT + 624, ++ .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP + 472, ++ .width = 9248, ++ .height = 6944, ++ }, ++ .timeperframe_default = { ++ .numerator = 100, ++ .denominator = 300 ++ }, ++ .reg_list = { ++ .num_of_regs = ARRAY_SIZE(mode_8000x6000_regs), ++ .regs = mode_8000x6000_regs, ++ } ++ }, { + .width = 4624, + .height = 3472, + .line_length_pix = 0x6397, diff --git a/target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch b/target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch new file mode 100644 index 0000000000..8f96b33baa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch @@ -0,0 +1,163 @@ +From b9d2d1862aa5b798cecb87a95d970ad34a4aebc0 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +Date: Tue, 30 May 2023 15:50:05 +0800 +Subject: [PATCH] media: i2c: arducam_64mp: Add PDAF support + +Enable PDAF output for all modes, and also need to modify Embedded Line +Width to 11560 * 3 (two lines of Embedded Data + one line of PDAF). + +Signed-off-by: Lee Jackson +--- + drivers/media/i2c/arducam_64mp.c | 64 ++++++++++++++++++++++++++++++-- + 1 file changed, 61 insertions(+), 3 deletions(-) + +--- a/drivers/media/i2c/arducam_64mp.c ++++ b/drivers/media/i2c/arducam_64mp.c +@@ -95,7 +95,7 @@ + #define ARDUCAM_64MP_TEST_PATTERN_GB_DEFAULT 0 + + /* Embedded metadata stream structure */ +-#define ARDUCAM_64MP_EMBEDDED_LINE_WIDTH 16384 ++#define ARDUCAM_64MP_EMBEDDED_LINE_WIDTH (11560 * 3) + #define ARDUCAM_64MP_NUM_EMBEDDED_LINES 1 + + enum pad_types { +@@ -144,6 +144,7 @@ struct arducam_64mp_mode { + }; + + static const struct arducam_64mp_reg mode_common_regs[] = { ++ {0x0100, 0x00}, + {0x0136, 0x18}, + {0x0137, 0x00}, + {0x33F0, 0x01}, +@@ -788,6 +789,7 @@ static const struct arducam_64mp_reg mod + {0x3092, 0x01}, + {0x3093, 0x00}, + {0x0350, 0x00}, ++ {0x3419, 0x00}, + }; + + /* 64 mpix 2.7fps */ +@@ -847,6 +849,14 @@ static const struct arducam_64mp_reg mod + {0x0205, 0x00}, + {0x020e, 0x01}, + {0x020f, 0x00}, ++ {0x341a, 0x00}, ++ {0x341b, 0x00}, ++ {0x341c, 0x00}, ++ {0x341d, 0x00}, ++ {0x341e, 0x02}, ++ {0x341f, 0x3c}, ++ {0x3420, 0x02}, ++ {0x3421, 0x42}, + }; + + /* 48 mpix 3.0fps */ +@@ -906,6 +916,14 @@ static const struct arducam_64mp_reg mod + {0x0205, 0x00}, + {0x020e, 0x01}, + {0x020f, 0x00}, ++ {0x341a, 0x00}, ++ {0x341b, 0x00}, ++ {0x341c, 0x00}, ++ {0x341d, 0x00}, ++ {0x341e, 0x01}, ++ {0x341f, 0xf4}, ++ {0x3420, 0x01}, ++ {0x3421, 0xf4}, + }; + + /* 16 mpix 10fps */ +@@ -959,6 +977,14 @@ static const struct arducam_64mp_reg mod + {0x98d8, 0x8c}, + {0x98d9, 0x0a}, + {0x99c4, 0x16}, ++ {0x341a, 0x00}, ++ {0x341b, 0x00}, ++ {0x341c, 0x00}, ++ {0x341d, 0x00}, ++ {0x341e, 0x01}, ++ {0x341f, 0x21}, ++ {0x3420, 0x01}, ++ {0x3421, 0x21}, + }; + + /* 4k 20fps mode */ +@@ -1012,6 +1038,14 @@ static const struct arducam_64mp_reg mod + {0x98d8, 0x8c}, + {0x98d9, 0x0a}, + {0x99c4, 0x16}, ++ {0x341a, 0x00}, ++ {0x341b, 0x00}, ++ {0x341c, 0x00}, ++ {0x341d, 0x00}, ++ {0x341e, 0x00}, ++ {0x341f, 0xf0}, ++ {0x3420, 0x00}, ++ {0x3421, 0xb4}, + }; + + /* 4x4 binned 30fps mode */ +@@ -1031,7 +1065,7 @@ static const struct arducam_64mp_reg mod + {0x0900, 0x01}, + {0x0901, 0x44}, + {0x0902, 0x08}, +- {0x30d8, 0x00}, ++ {0x30d8, 0x04}, + {0x3200, 0x43}, + {0x3201, 0x43}, + {0x0408, 0x00}, +@@ -1046,7 +1080,7 @@ static const struct arducam_64mp_reg mod + {0x034d, 0x08}, + {0x034e, 0x06}, + {0x034f, 0xc8}, +- {0x30d9, 0x01}, ++ {0x30d9, 0x00}, + {0x32d5, 0x00}, + {0x32d6, 0x00}, + {0x401e, 0x00}, +@@ -1065,6 +1099,14 @@ static const struct arducam_64mp_reg mod + {0x98d8, 0x8c}, + {0x98d9, 0x0a}, + {0x99c4, 0x16}, ++ {0x341a, 0x00}, ++ {0x341b, 0x00}, ++ {0x341c, 0x00}, ++ {0x341d, 0x00}, ++ {0x341e, 0x00}, ++ {0x341f, 0x90}, ++ {0x3420, 0x00}, ++ {0x3421, 0x90}, + }; + + /* 1080p 60fps mode */ +@@ -1118,6 +1160,14 @@ static const struct arducam_64mp_reg mod + {0x98d8, 0x8c}, + {0x98d9, 0x0a}, + {0x99c4, 0x16}, ++ {0x341a, 0x00}, ++ {0x341b, 0x00}, ++ {0x341c, 0x00}, ++ {0x341d, 0x00}, ++ {0x341e, 0x00}, ++ {0x341f, 0x78}, ++ {0x3420, 0x00}, ++ {0x3421, 0x5a}, + }; + + /* 720p 120fps mode */ +@@ -1171,6 +1221,14 @@ static const struct arducam_64mp_reg mod + {0x98d8, 0x8c}, + {0x98d9, 0x0a}, + {0x99c4, 0x16}, ++ {0x341a, 0x00}, ++ {0x341b, 0x00}, ++ {0x341c, 0x00}, ++ {0x341d, 0x00}, ++ {0x341e, 0x00}, ++ {0x341f, 0x50}, ++ {0x3420, 0x00}, ++ {0x3421, 0x3c}, + }; + + /* Mode configs */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch b/target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch new file mode 100644 index 0000000000..bf1646322b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch @@ -0,0 +1,24 @@ +From 6f4106f7a7fdcbc03290008713915b4122988c90 Mon Sep 17 00:00:00 2001 +From: James Hughes +Date: Wed, 5 Jul 2023 15:43:30 +0100 +Subject: [PATCH] overlays: audremap: Document CM4 40&41 restriction + +Update audremap information to state pins 40,41 are not available on the CM4. + +Signed-off-by: James Hughes (james.hughes@raspberrypi.com) +--- + arch/arm/boot/dts/overlays/README | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -703,7 +703,8 @@ Params: swap_lr Reverse + nothing on BCM2711 (default off) + pins_12_13 Select GPIOs 12 & 13 (default) + pins_18_19 Select GPIOs 18 & 19 +- pins_40_41 Select GPIOs 40 & 41 ++ pins_40_41 Select GPIOs 40 & 41 (not available on CM4, used ++ for other purposes) + pins_40_45 Select GPIOs 40 & 45 (don't use on BCM2711 - the + pins are on different controllers) + diff --git a/target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch b/target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch new file mode 100644 index 0000000000..9265e931fa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch @@ -0,0 +1,120 @@ +From 1d15e6a34222cc8d8eb1050e7a3e276b0348be41 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 3 Jul 2023 11:04:56 +0100 +Subject: [PATCH] fixup! Allow mac address to be set in smsc95xx + +usbnet: smsc95xx: Fix indentation of smsc95xx_is_macaddr_param() + +smsc95xx_is_macaddr_param() is incorrectly indented, it uses 7 spaces +instead of tabs. Fix it. + +Fixes: aac7b105788e ("Allow mac address to be set in smsc95xx") +Signed-off-by: Philipp Rosenberger +[lukas: fix netif_dbg() indentation as well, wordsmith commit message] +Signed-off-by: Lukas Wunner + +usbnet: smsc95xx: Simplify MAC address parsing + +Parsing the MAC address provided on the kernel command line can be +simplified quite a bit by taking advantage of the kernel's built-in +mac_pton() helper. + +Likewise emitting the MAC address can be simplified with the %pM +format string conversion. + +Signed-off-by: Lukas Wunner + +usbnet: smsc95xx: Fix style issues in smsc95xx_is_macaddr_param() + +It is bad practice to have a function named ..._is_...() which has side +effects. So drop the 'is' from the name. + +Per kernel convention return 0 on success and a negative errno on +failure. + +Validate the MAC address retrieved from the command line. + +Signed-off-by: Philipp Rosenberger +[lukas: leave 2nd function parameter unchanged, wordsmith commit message] +Signed-off-by: Lukas Wunner +--- + drivers/net/usb/smsc95xx.c | 61 +++++++++++--------------------------- + 1 file changed, 17 insertions(+), 44 deletions(-) + +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -814,49 +814,18 @@ static int smsc95xx_ioctl(struct net_dev + } + + /* Check the macaddr module parameter for a MAC address */ +-static int smsc95xx_is_macaddr_param(struct usbnet *dev, struct net_device *nd) ++static int smsc95xx_macaddr_param(struct usbnet *dev, struct net_device *nd) + { +- int i, j, got_num, num; +- u8 mtbl[ETH_ALEN]; ++ u8 mtbl[ETH_ALEN]; + +- if (macaddr[0] == ':') +- return 0; +- +- i = 0; +- j = 0; +- num = 0; +- got_num = 0; +- while (j < ETH_ALEN) { +- if (macaddr[i] && macaddr[i] != ':') { +- got_num++; +- if ('0' <= macaddr[i] && macaddr[i] <= '9') +- num = num * 16 + macaddr[i] - '0'; +- else if ('A' <= macaddr[i] && macaddr[i] <= 'F') +- num = num * 16 + 10 + macaddr[i] - 'A'; +- else if ('a' <= macaddr[i] && macaddr[i] <= 'f') +- num = num * 16 + 10 + macaddr[i] - 'a'; +- else +- break; +- i++; +- } else if (got_num == 2) { +- mtbl[j++] = (u8) num; +- num = 0; +- got_num = 0; +- i++; +- } else { +- break; +- } +- } +- +- if (j == ETH_ALEN) { +- netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: " +- "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2], +- mtbl[3], mtbl[4], mtbl[5]); +- dev_addr_mod(nd, 0, mtbl, ETH_ALEN); +- return 1; +- } else { +- return 0; +- } ++ if (mac_pton(macaddr, mtbl)) { ++ netif_dbg(dev, ifup, dev->net, ++ "Overriding MAC address with: %pM\n", mtbl); ++ dev_addr_mod(nd, 0, mtbl, ETH_ALEN); ++ return 0; ++ } else { ++ return -EINVAL; ++ } + } + + static void smsc95xx_init_mac_address(struct usbnet *dev) +@@ -883,8 +852,12 @@ static void smsc95xx_init_mac_address(st + } + + /* Check module parameters */ +- if (smsc95xx_is_macaddr_param(dev, dev->net)) +- return; ++ if (smsc95xx_macaddr_param(dev, dev->net) == 0) { ++ if (is_valid_ether_addr(dev->net->dev_addr)) { ++ netif_dbg(dev, ifup, dev->net, "MAC address read from module parameter\n"); ++ return; ++ } ++ } + + /* no useful static MAC address found. generate a random one */ + eth_hw_addr_random(dev->net); diff --git a/target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch b/target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch new file mode 100644 index 0000000000..593c95e2a2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch @@ -0,0 +1,1455 @@ +From a2d2745c311baa588fb0fffbe38076294f06b7c0 Mon Sep 17 00:00:00 2001 +From: Nicolai Buchwitz +Date: Wed, 12 Jul 2023 11:30:42 +0200 +Subject: [PATCH] cfg80211: ship debian certificates as hex files + +Loading the regulatory database from the debian files fails with + +"loaded regulatory.db is malformed or signature is missing/invalid" + +due to missing certificates. Add these debian-specific certificates +from upstream to fix this error. See #5536 for details. + +The certificates have been imported as following: + +patch -p1 <<<$( +curl https://salsa.debian.org/kernel-team/linux/-/raw/\ +master/debian/patches/debian/\ +wireless-add-debian-wireless-regdb-certificates.patch +) + +Signed-off-by: Nicolai Buchwitz +--- + net/wireless/certs/debian.hex | 1426 +++++++++++++++++++++++++++++++++ + 1 file changed, 1426 insertions(+) + create mode 100644 net/wireless/certs/debian.hex + +--- /dev/null ++++ b/net/wireless/certs/debian.hex +@@ -0,0 +1,1426 @@ ++0x30, ++0x82, ++0x02, ++0xbd, ++0x30, ++0x82, ++0x01, ++0xa5, ++0x02, ++0x14, ++0x57, ++0x7e, ++0x02, ++0x1c, ++0xb9, ++0x80, ++0xe0, ++0xe8, ++0x20, ++0x82, ++0x1b, ++0xa7, ++0xb5, ++0x4b, ++0x49, ++0x61, ++0xb8, ++0xb4, ++0xfa, ++0xdf, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x30, ++0x1a, ++0x31, ++0x18, ++0x30, ++0x16, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x0f, ++0x62, ++0x65, ++0x6e, ++0x68, ++0x40, ++0x64, ++0x65, ++0x62, ++0x69, ++0x61, ++0x6e, ++0x2e, ++0x6f, ++0x72, ++0x67, ++0x30, ++0x20, ++0x17, ++0x0d, ++0x32, ++0x30, ++0x30, ++0x31, ++0x33, ++0x30, ++0x31, ++0x33, ++0x32, ++0x36, ++0x31, ++0x33, ++0x5a, ++0x18, ++0x0f, ++0x32, ++0x31, ++0x32, ++0x30, ++0x30, ++0x31, ++0x30, ++0x36, ++0x31, ++0x33, ++0x32, ++0x36, ++0x31, ++0x33, ++0x5a, ++0x30, ++0x1a, ++0x31, ++0x18, ++0x30, ++0x16, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x0f, ++0x62, ++0x65, ++0x6e, ++0x68, ++0x40, ++0x64, ++0x65, ++0x62, ++0x69, ++0x61, ++0x6e, ++0x2e, ++0x6f, ++0x72, ++0x67, ++0x30, ++0x82, ++0x01, ++0x22, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x01, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x0f, ++0x00, ++0x30, ++0x82, ++0x01, ++0x0a, ++0x02, ++0x82, ++0x01, ++0x01, ++0x00, ++0x9d, ++0xe1, ++0x77, ++0xa0, ++0x24, ++0xa0, ++0xd5, ++0x79, ++0x65, ++0x3a, ++0x07, ++0x90, ++0xc9, ++0xf6, ++0xa5, ++0xa6, ++0x1f, ++0x84, ++0x1c, ++0x23, ++0x07, ++0x4b, ++0x4f, ++0xa5, ++0x03, ++0xc6, ++0x0f, ++0xf7, ++0x54, ++0xd5, ++0x8b, ++0x7e, ++0x79, ++0x81, ++0x00, ++0xd2, ++0xe9, ++0x3d, ++0xf4, ++0x97, ++0xfe, ++0x84, ++0xcd, ++0x55, ++0xbd, ++0xc9, ++0x8f, ++0x21, ++0x57, ++0x88, ++0x06, ++0x39, ++0x90, ++0x66, ++0x41, ++0x26, ++0x79, ++0x2c, ++0xca, ++0x3f, ++0x95, ++0x87, ++0x01, ++0x11, ++0x2f, ++0x2f, ++0xb0, ++0xe1, ++0x0b, ++0x43, ++0xfc, ++0x5f, ++0x2f, ++0x4f, ++0x67, ++0x04, ++0xdb, ++0x4d, ++0xb7, ++0x72, ++0x4d, ++0xd1, ++0xc5, ++0x76, ++0x73, ++0x4d, ++0x91, ++0x69, ++0xb0, ++0x71, ++0x17, ++0x36, ++0xea, ++0xab, ++0x0a, ++0x3a, ++0xcd, ++0x95, ++0x9b, ++0x76, ++0x1b, ++0x8e, ++0x21, ++0x17, ++0x8f, ++0xc5, ++0x02, ++0xbf, ++0x24, ++0xc7, ++0xc0, ++0x40, ++0xb1, ++0x3b, ++0xc4, ++0x80, ++0x7c, ++0x71, ++0xa5, ++0x51, ++0xdc, ++0xf7, ++0x3a, ++0x58, ++0x7f, ++0xb1, ++0x07, ++0x81, ++0x8a, ++0x10, ++0xd1, ++0xf6, ++0x93, ++0x17, ++0x71, ++0xe0, ++0xfa, ++0x51, ++0x79, ++0x15, ++0xd4, ++0xd7, ++0x8f, ++0xad, ++0xbd, ++0x6f, ++0x38, ++0xe1, ++0x26, ++0x7d, ++0xbc, ++0xf0, ++0x3e, ++0x80, ++0x89, ++0xb4, ++0xec, ++0x8e, ++0x69, ++0x90, ++0xdb, ++0x97, ++0x8a, ++0xf0, ++0x23, ++0x23, ++0x83, ++0x82, ++0x3b, ++0x6a, ++0xb1, ++0xac, ++0xeb, ++0xe7, ++0x99, ++0x74, ++0x2a, ++0x35, ++0x8e, ++0xa9, ++0x64, ++0xfd, ++0x46, ++0x9e, ++0xe8, ++0xe5, ++0x48, ++0x61, ++0x31, ++0x6e, ++0xe6, ++0xfc, ++0x19, ++0x18, ++0x54, ++0xc3, ++0x1b, ++0x4f, ++0xd6, ++0x00, ++0x44, ++0x87, ++0x1c, ++0x37, ++0x45, ++0xea, ++0xf5, ++0xc9, ++0xcb, ++0x0f, ++0x0c, ++0x55, ++0xec, ++0xcf, ++0x6a, ++0xc2, ++0x45, ++0x26, ++0x23, ++0xa2, ++0x31, ++0x52, ++0x4d, ++0xee, ++0x21, ++0x7d, ++0xfd, ++0x58, ++0x72, ++0xc2, ++0x28, ++0xc5, ++0x8e, ++0xa9, ++0xd0, ++0xee, ++0x01, ++0x77, ++0x08, ++0xa5, ++0xf0, ++0x22, ++0x2b, ++0x47, ++0x79, ++0x2b, ++0xcf, ++0x9a, ++0x46, ++0xb5, ++0x8f, ++0xfd, ++0x64, ++0xa2, ++0xb5, ++0xed, ++0x02, ++0x03, ++0x01, ++0x00, ++0x01, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x01, ++0x00, ++0x20, ++0x44, ++0xfe, ++0xa9, ++0x9e, ++0xdd, ++0x9b, ++0xea, ++0xce, ++0x25, ++0x75, ++0x08, ++0xf0, ++0x2b, ++0x53, ++0xf7, ++0x5a, ++0x36, ++0x1c, ++0x4a, ++0x23, ++0x7f, ++0xd0, ++0x41, ++0x3c, ++0x12, ++0x2b, ++0xb9, ++0x80, ++0x4e, ++0x8a, ++0x15, ++0x5d, ++0x1f, ++0x40, ++0xa7, ++0x26, ++0x28, ++0x32, ++0xc3, ++0x5b, ++0x06, ++0x28, ++0x2d, ++0x3d, ++0x08, ++0x09, ++0x1e, ++0x01, ++0xe9, ++0x67, ++0xe3, ++0x33, ++0xe6, ++0x15, ++0x45, ++0x39, ++0xee, ++0x17, ++0x83, ++0xdb, ++0x42, ++0xff, ++0x7f, ++0x35, ++0xf4, ++0xac, ++0x16, ++0xdb, ++0xba, ++0xb8, ++0x1a, ++0x20, ++0x21, ++0x41, ++0xff, ++0xf3, ++0x92, ++0xff, ++0x65, ++0x6e, ++0x29, ++0x16, ++0xd0, ++0xbf, ++0x8d, ++0xdf, ++0x48, ++0x2c, ++0x73, ++0x36, ++0x7f, ++0x22, ++0xe6, ++0xee, ++0x78, ++0xb4, ++0x63, ++0x83, ++0x0e, ++0x39, ++0xeb, ++0xaf, ++0x10, ++0x2a, ++0x90, ++0xd3, ++0xfc, ++0xe6, ++0xc3, ++0x8f, ++0x97, ++0x5b, ++0x76, ++0xbf, ++0x9b, ++0xf5, ++0x98, ++0xd2, ++0x53, ++0x06, ++0x8b, ++0xf8, ++0xa4, ++0x04, ++0x9b, ++0x1b, ++0x62, ++0x6a, ++0x9d, ++0xac, ++0xe6, ++0x4b, ++0x0d, ++0xc9, ++0xd7, ++0x56, ++0x63, ++0x15, ++0x01, ++0x38, ++0x8c, ++0xbe, ++0xf1, ++0x44, ++0xc4, ++0x38, ++0x27, ++0xe0, ++0xcf, ++0x72, ++0xd6, ++0x3d, ++0xe4, ++0xf7, ++0x4b, ++0x3b, ++0xd2, ++0xb1, ++0x0c, ++0xd5, ++0x83, ++0x6d, ++0x1e, ++0x10, ++0x04, ++0x69, ++0x29, ++0x88, ++0x69, ++0xe0, ++0x7d, ++0xd7, ++0xdb, ++0xb4, ++0x59, ++0x72, ++0x8d, ++0x9d, ++0x3c, ++0x43, ++0xaf, ++0xc6, ++0x7d, ++0xb7, ++0x21, ++0x15, ++0x52, ++0x8a, ++0xe9, ++0x9b, ++0x6b, ++0x2e, ++0xe8, ++0x27, ++0x3c, ++0x3f, ++0x2d, ++0x84, ++0xfb, ++0x9a, ++0x22, ++0x0a, ++0x9f, ++0x6a, ++0x25, ++0xe6, ++0x39, ++0xe4, ++0x74, ++0x73, ++0xb6, ++0x2a, ++0x70, ++0xaa, ++0x1d, ++0xcb, ++0xcc, ++0xd4, ++0xa0, ++0x1b, ++0x26, ++0x71, ++0x63, ++0x04, ++0xc5, ++0x12, ++0x21, ++0x48, ++0xba, ++0x92, ++0x27, ++0x06, ++0xa8, ++0x3e, ++0x6d, ++0xa1, ++0x43, ++0xa5, ++0xd2, ++0x2a, ++0xf7, ++0xca, ++0xc4, ++0x26, ++0xe8, ++0x5b, ++0x1f, ++0xe4, ++0xdc, ++0x89, ++0xdc, ++0x1f, ++0x04, ++0x79, ++0x3f, ++0x30, ++0x82, ++0x02, ++0xcd, ++0x30, ++0x82, ++0x01, ++0xb5, ++0x02, ++0x14, ++0x3a, ++0xbb, ++0xc6, ++0xec, ++0x14, ++0x6e, ++0x09, ++0xd1, ++0xb6, ++0x01, ++0x6a, ++0xb9, ++0xd6, ++0xcf, ++0x71, ++0xdd, ++0x23, ++0x3f, ++0x03, ++0x28, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x30, ++0x22, ++0x31, ++0x20, ++0x30, ++0x1e, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x17, ++0x72, ++0x6f, ++0x6d, ++0x61, ++0x69, ++0x6e, ++0x2e, ++0x70, ++0x65, ++0x72, ++0x69, ++0x65, ++0x72, ++0x40, ++0x67, ++0x6d, ++0x61, ++0x69, ++0x6c, ++0x2e, ++0x63, ++0x6f, ++0x6d, ++0x30, ++0x20, ++0x17, ++0x0d, ++0x32, ++0x30, ++0x30, ++0x32, ++0x32, ++0x34, ++0x31, ++0x39, ++0x30, ++0x31, ++0x34, ++0x34, ++0x5a, ++0x18, ++0x0f, ++0x32, ++0x31, ++0x32, ++0x30, ++0x30, ++0x31, ++0x33, ++0x31, ++0x31, ++0x39, ++0x30, ++0x31, ++0x34, ++0x34, ++0x5a, ++0x30, ++0x22, ++0x31, ++0x20, ++0x30, ++0x1e, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x17, ++0x72, ++0x6f, ++0x6d, ++0x61, ++0x69, ++0x6e, ++0x2e, ++0x70, ++0x65, ++0x72, ++0x69, ++0x65, ++0x72, ++0x40, ++0x67, ++0x6d, ++0x61, ++0x69, ++0x6c, ++0x2e, ++0x63, ++0x6f, ++0x6d, ++0x30, ++0x82, ++0x01, ++0x22, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x01, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x0f, ++0x00, ++0x30, ++0x82, ++0x01, ++0x0a, ++0x02, ++0x82, ++0x01, ++0x01, ++0x00, ++0xf0, ++0xb8, ++0x4f, ++0x3f, ++0x70, ++0x78, ++0xf8, ++0x74, ++0x45, ++0xa2, ++0x28, ++0xaf, ++0x04, ++0x75, ++0x04, ++0xa3, ++0xf3, ++0xa7, ++0xc7, ++0x04, ++0xac, ++0xb6, ++0xe1, ++0xfc, ++0xe1, ++0xc0, ++0x3d, ++0xe0, ++0x26, ++0x90, ++0x8a, ++0x45, ++0x60, ++0xc4, ++0x75, ++0xf3, ++0x1a, ++0x33, ++0x37, ++0x56, ++0x7d, ++0x30, ++0x07, ++0x75, ++0x0e, ++0xa6, ++0x79, ++0x06, ++0x95, ++0x9d, ++0x17, ++0x3c, ++0x09, ++0xa9, ++0x7f, ++0xab, ++0x95, ++0x5d, ++0xed, ++0xe0, ++0x75, ++0x26, ++0x2f, ++0x65, ++0x65, ++0xcd, ++0x61, ++0xb1, ++0x33, ++0x27, ++0x67, ++0x41, ++0xa1, ++0x01, ++0x13, ++0xe9, ++0x13, ++0x6a, ++0x6d, ++0x4e, ++0x98, ++0xe1, ++0x9e, ++0x7b, ++0x0b, ++0x5b, ++0x44, ++0xef, ++0x68, ++0x5a, ++0x6f, ++0x7d, ++0x97, ++0xa1, ++0x33, ++0x22, ++0x97, ++0x12, ++0x21, ++0x09, ++0x8f, ++0x90, ++0xe0, ++0x25, ++0x94, ++0xdd, ++0x8a, ++0x3a, ++0xf7, ++0x4a, ++0x60, ++0x04, ++0x26, ++0x6d, ++0x00, ++0x82, ++0xe4, ++0xcf, ++0x64, ++0x1c, ++0x79, ++0x15, ++0x24, ++0xf2, ++0x42, ++0x86, ++0xf5, ++0x10, ++0x86, ++0xac, ++0x20, ++0x88, ++0x90, ++0x87, ++0xdf, ++0x8c, ++0x37, ++0x7c, ++0xbf, ++0x35, ++0xd5, ++0x6f, ++0x9f, ++0x77, ++0xc3, ++0xcd, ++0x69, ++0x25, ++0x06, ++0xc2, ++0x65, ++0x51, ++0x71, ++0x89, ++0x7f, ++0x6e, ++0x4d, ++0xe5, ++0xd5, ++0x8a, ++0x36, ++0x1a, ++0xad, ++0xc1, ++0x18, ++0xd6, ++0x14, ++0x42, ++0x87, ++0xf0, ++0x93, ++0x83, ++0xf1, ++0x99, ++0x74, ++0xc4, ++0x13, ++0xaa, ++0x3b, ++0x66, ++0x85, ++0x6f, ++0xe0, ++0xbc, ++0x5f, ++0xb6, ++0x40, ++0xa6, ++0x41, ++0x06, ++0x0a, ++0xba, ++0x0e, ++0xe9, ++0x32, ++0x44, ++0x10, ++0x39, ++0x53, ++0xcd, ++0xbf, ++0xf3, ++0xd3, ++0x26, ++0xf6, ++0xb6, ++0x2b, ++0x40, ++0x2e, ++0xb9, ++0x88, ++0xc1, ++0xf4, ++0xe3, ++0xa0, ++0x28, ++0x77, ++0x4f, ++0xba, ++0xa8, ++0xca, ++0x9c, ++0x05, ++0xba, ++0x88, ++0x96, ++0x99, ++0x54, ++0x89, ++0xa2, ++0x8d, ++0xf3, ++0x73, ++0xa1, ++0x8c, ++0x4a, ++0xa8, ++0x71, ++0xee, ++0x2e, ++0xd2, ++0x83, ++0x14, ++0x48, ++0xbd, ++0x98, ++0xc6, ++0xce, ++0xdc, ++0xa8, ++0xa3, ++0x97, ++0x2e, ++0x40, ++0x16, ++0x2f, ++0x02, ++0x03, ++0x01, ++0x00, ++0x01, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x01, ++0x00, ++0x76, ++0x5d, ++0x03, ++0x3d, ++0xb6, ++0x96, ++0x00, ++0x1b, ++0x6e, ++0x0c, ++0xdd, ++0xbb, ++0xc8, ++0xdf, ++0xbc, ++0xeb, ++0x6c, ++0x01, ++0x40, ++0x1a, ++0x2b, ++0x07, ++0x60, ++0xa1, ++0x1a, ++0xe1, ++0x43, ++0x57, ++0xfa, ++0xbe, ++0xde, ++0xbb, ++0x8f, ++0x73, ++0xf3, ++0x92, ++0xa2, ++0xaa, ++0x83, ++0x01, ++0xc1, ++0x17, ++0xe4, ++0x9d, ++0x09, ++0x41, ++0xe0, ++0x32, ++0x33, ++0x97, ++0x4b, ++0xf2, ++0xdc, ++0x0f, ++0x8b, ++0xa8, ++0xb8, ++0x5a, ++0x04, ++0x86, ++0xf6, ++0x71, ++0xa1, ++0x97, ++0xd0, ++0x54, ++0x56, ++0x10, ++0x8e, ++0x54, ++0x99, ++0x0d, ++0x2a, ++0xa9, ++0xaf, ++0x1b, ++0x55, ++0x59, ++0x06, ++0x2b, ++0xa4, ++0x5f, ++0xb1, ++0x54, ++0xa6, ++0xec, ++0xc7, ++0xd6, ++0x43, ++0xee, ++0x86, ++0x2c, ++0x9b, ++0x18, ++0x9d, ++0x8f, ++0x00, ++0x82, ++0xc1, ++0x88, ++0x61, ++0x16, ++0x85, ++0x3c, ++0x17, ++0x56, ++0xfe, ++0x6a, ++0xa0, ++0x7a, ++0x68, ++0xc5, ++0x7b, ++0x3d, ++0x3c, ++0xb6, ++0x13, ++0x18, ++0x99, ++0x6d, ++0x74, ++0x65, ++0x13, ++0x67, ++0xb7, ++0xfc, ++0x5a, ++0x44, ++0x48, ++0x72, ++0xa0, ++0x73, ++0xb8, ++0xff, ++0x02, ++0x9d, ++0x7c, ++0x5b, ++0xf9, ++0x7c, ++0x75, ++0x0a, ++0x3c, ++0x81, ++0x80, ++0x3c, ++0x41, ++0xf2, ++0xd5, ++0xfa, ++0x3d, ++0x1f, ++0xe3, ++0xda, ++0x8c, ++0xa5, ++0x17, ++0x1f, ++0x53, ++0x1a, ++0x75, ++0xad, ++0x4e, ++0x11, ++0x1c, ++0x07, ++0xec, ++0x0a, ++0x69, ++0xfd, ++0x33, ++0xfa, ++0x32, ++0x7e, ++0x66, ++0xf5, ++0x29, ++0xe8, ++0x4d, ++0x8a, ++0xfa, ++0x0d, ++0x4b, ++0x68, ++0xc3, ++0x95, ++0x11, ++0xba, ++0x6f, ++0x1e, ++0x07, ++0x8c, ++0x85, ++0xc7, ++0xc7, ++0xc9, ++0xc1, ++0x30, ++0xa3, ++0x70, ++0xb0, ++0xa1, ++0xe0, ++0xd5, ++0x85, ++0x15, ++0x94, ++0x77, ++0xc1, ++0x1c, ++0x91, ++0xf1, ++0x5f, ++0x50, ++0xcd, ++0x2c, ++0x57, ++0x4b, ++0x22, ++0x4f, ++0xee, ++0x95, ++0xd7, ++0xa7, ++0xa4, ++0x59, ++0x62, ++0xae, ++0xb9, ++0xbf, ++0xd7, ++0x63, ++0x5a, ++0x04, ++0xfc, ++0x24, ++0x11, ++0xae, ++0x34, ++0x4b, ++0xf4, ++0x0c, ++0x9f, ++0x0b, ++0x59, ++0x7d, ++0x27, ++0x39, ++0x54, ++0x69, ++0x4f, ++0xfd, ++0x6e, ++0x44, ++0x9f, ++0x21, diff --git a/target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch b/target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch new file mode 100644 index 0000000000..87097d2bbf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch @@ -0,0 +1,329 @@ +From 3ece03b1575b0c3a0989e372aaaa4557ae74dc89 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 20 Jul 2023 11:28:20 +0100 +Subject: [PATCH] fixup! Add support for all the downstream rpi sound card + drivers + +Replace the Allo Dac clock driver with an extension of the +HiFiBerry clock driver that it cloned. + +Signed-off-by: Phil Elwell +--- + drivers/clk/Makefile | 1 - + drivers/clk/clk-allo-dac.c | 161 ----------------------------- + drivers/clk/clk-hifiberry-dacpro.c | 57 ++++++---- + sound/soc/bcm/Kconfig | 1 + + 4 files changed, 40 insertions(+), 180 deletions(-) + delete mode 100644 drivers/clk/clk-allo-dac.c + +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -19,7 +19,6 @@ endif + + # hardware specific clock types + # please keep this section sorted lexicographically by file path name +-obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += clk-allo-dac.o + obj-$(CONFIG_COMMON_CLK_APPLE_NCO) += clk-apple-nco.o + obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o + obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o +--- a/drivers/clk/clk-allo-dac.c ++++ /dev/null +@@ -1,161 +0,0 @@ +-/* +- * Clock Driver for Allo DAC +- * +- * Author: Baswaraj K +- * Copyright 2016 +- * based on code by Stuart MacLean +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* Clock rate of CLK44EN attached to GPIO6 pin */ +-#define CLK_44EN_RATE 45158400UL +-/* Clock rate of CLK48EN attached to GPIO3 pin */ +-#define CLK_48EN_RATE 49152000UL +- +-/** +- * struct allo_dac_clk - Common struct to the Allo DAC +- * @hw: clk_hw for the common clk framework +- * @mode: 0 => CLK44EN, 1 => CLK48EN +- */ +-struct clk_allo_hw { +- struct clk_hw hw; +- uint8_t mode; +-}; +- +-#define to_allo_clk(_hw) container_of(_hw, struct clk_allo_hw, hw) +- +-static const struct of_device_id clk_allo_dac_dt_ids[] = { +- { .compatible = "allo,dac-clk",}, +- { } +-}; +-MODULE_DEVICE_TABLE(of, clk_allo_dac_dt_ids); +- +-static unsigned long clk_allo_dac_recalc_rate(struct clk_hw *hw, +- unsigned long parent_rate) +-{ +- return (to_allo_clk(hw)->mode == 0) ? CLK_44EN_RATE : +- CLK_48EN_RATE; +-} +- +-static long clk_allo_dac_round_rate(struct clk_hw *hw, +- unsigned long rate, unsigned long *parent_rate) +-{ +- long actual_rate; +- +- if (rate <= CLK_44EN_RATE) { +- actual_rate = (long)CLK_44EN_RATE; +- } else if (rate >= CLK_48EN_RATE) { +- actual_rate = (long)CLK_48EN_RATE; +- } else { +- long diff44Rate = (long)(rate - CLK_44EN_RATE); +- long diff48Rate = (long)(CLK_48EN_RATE - rate); +- +- if (diff44Rate < diff48Rate) +- actual_rate = (long)CLK_44EN_RATE; +- else +- actual_rate = (long)CLK_48EN_RATE; +- } +- return actual_rate; +-} +- +- +-static int clk_allo_dac_set_rate(struct clk_hw *hw, +- unsigned long rate, unsigned long parent_rate) +-{ +- unsigned long actual_rate; +- struct clk_allo_hw *clk = to_allo_clk(hw); +- +- actual_rate = (unsigned long)clk_allo_dac_round_rate(hw, rate, +- &parent_rate); +- clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1; +- return 0; +-} +- +- +-const struct clk_ops clk_allo_dac_rate_ops = { +- .recalc_rate = clk_allo_dac_recalc_rate, +- .round_rate = clk_allo_dac_round_rate, +- .set_rate = clk_allo_dac_set_rate, +-}; +- +-static int clk_allo_dac_probe(struct platform_device *pdev) +-{ +- int ret; +- struct clk_allo_hw *proclk; +- struct clk *clk; +- struct device *dev; +- struct clk_init_data init; +- +- dev = &pdev->dev; +- +- proclk = kzalloc(sizeof(struct clk_allo_hw), GFP_KERNEL); +- if (!proclk) +- return -ENOMEM; +- +- init.name = "clk-allo-dac"; +- init.ops = &clk_allo_dac_rate_ops; +- init.flags = 0; +- init.parent_names = NULL; +- init.num_parents = 0; +- +- proclk->mode = 0; +- proclk->hw.init = &init; +- +- clk = devm_clk_register(dev, &proclk->hw); +- if (!IS_ERR(clk)) { +- ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, +- clk); +- } else { +- dev_err(dev, "Fail to register clock driver\n"); +- kfree(proclk); +- ret = PTR_ERR(clk); +- } +- return ret; +-} +- +-static int clk_allo_dac_remove(struct platform_device *pdev) +-{ +- of_clk_del_provider(pdev->dev.of_node); +- return 0; +-} +- +-static struct platform_driver clk_allo_dac_driver = { +- .probe = clk_allo_dac_probe, +- .remove = clk_allo_dac_remove, +- .driver = { +- .name = "clk-allo-dac", +- .of_match_table = clk_allo_dac_dt_ids, +- }, +-}; +- +-static int __init clk_allo_dac_init(void) +-{ +- return platform_driver_register(&clk_allo_dac_driver); +-} +-core_initcall(clk_allo_dac_init); +- +-static void __exit clk_allo_dac_exit(void) +-{ +- platform_driver_unregister(&clk_allo_dac_driver); +-} +-module_exit(clk_allo_dac_exit); +- +-MODULE_DESCRIPTION("Allo DAC clock driver"); +-MODULE_LICENSE("GPL v2"); +-MODULE_ALIAS("platform:clk-allo-dac"); +--- a/drivers/clk/clk-hifiberry-dacpro.c ++++ b/drivers/clk/clk-hifiberry-dacpro.c +@@ -22,10 +22,12 @@ + #include + #include + +-/* Clock rate of CLK44EN attached to GPIO6 pin */ +-#define CLK_44EN_RATE 22579200UL +-/* Clock rate of CLK48EN attached to GPIO3 pin */ +-#define CLK_48EN_RATE 24576000UL ++struct ext_clk_rates { ++ /* Clock rate of CLK44EN attached to GPIO6 pin */ ++ unsigned long clk_44en; ++ /* Clock rate of CLK48EN attached to GPIO3 pin */ ++ unsigned long clk_48en; ++}; + + /** + * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro +@@ -35,12 +37,24 @@ + struct clk_hifiberry_hw { + struct clk_hw hw; + uint8_t mode; ++ struct ext_clk_rates clk_rates; + }; + + #define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw) + ++static const struct ext_clk_rates hifiberry_dacpro_clks = { ++ .clk_44en = 22579200UL, ++ .clk_48en = 24576000UL, ++}; ++ ++static const struct ext_clk_rates allo_dac_clks = { ++ .clk_44en = 45158400UL, ++ .clk_48en = 49152000UL, ++}; ++ + static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = { +- { .compatible = "hifiberry,dacpro-clk",}, ++ { .compatible = "hifiberry,dacpro-clk", &hifiberry_dacpro_clks }, ++ { .compatible = "allo,dac-clk", &allo_dac_clks }, + { } + }; + MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids); +@@ -48,27 +62,29 @@ MODULE_DEVICE_TABLE(of, clk_hifiberry_da + static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +- return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE : +- CLK_48EN_RATE; ++ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); ++ return (clk->mode == 0) ? clk->clk_rates.clk_44en : ++ clk->clk_rates.clk_48en; + } + + static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate) + { ++ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); + long actual_rate; + +- if (rate <= CLK_44EN_RATE) { +- actual_rate = (long)CLK_44EN_RATE; +- } else if (rate >= CLK_48EN_RATE) { +- actual_rate = (long)CLK_48EN_RATE; ++ if (rate <= clk->clk_rates.clk_44en) { ++ actual_rate = (long)clk->clk_rates.clk_44en; ++ } else if (rate >= clk->clk_rates.clk_48en) { ++ actual_rate = (long)clk->clk_rates.clk_48en; + } else { +- long diff44Rate = (long)(rate - CLK_44EN_RATE); +- long diff48Rate = (long)(CLK_48EN_RATE - rate); ++ long diff44Rate = (long)(rate - clk->clk_rates.clk_44en); ++ long diff48Rate = (long)(clk->clk_rates.clk_48en - rate); + + if (diff44Rate < diff48Rate) +- actual_rate = (long)CLK_44EN_RATE; ++ actual_rate = (long)clk->clk_rates.clk_44en; + else +- actual_rate = (long)CLK_48EN_RATE; ++ actual_rate = (long)clk->clk_rates.clk_48en; + } + return actual_rate; + } +@@ -77,12 +93,12 @@ static long clk_hifiberry_dacpro_round_r + static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate) + { +- unsigned long actual_rate; + struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); ++ unsigned long actual_rate; + + actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate, + &parent_rate); +- clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1; ++ clk->mode = (actual_rate == clk->clk_rates.clk_44en) ? 0 : 1; + return 0; + } + +@@ -95,13 +111,17 @@ const struct clk_ops clk_hifiberry_dacpr + + static int clk_hifiberry_dacpro_probe(struct platform_device *pdev) + { +- int ret; ++ const struct of_device_id *of_id; + struct clk_hifiberry_hw *proclk; + struct clk *clk; + struct device *dev; + struct clk_init_data init; ++ int ret; + + dev = &pdev->dev; ++ of_id = of_match_node(clk_hifiberry_dacpro_dt_ids, dev->of_node); ++ if (!of_id) ++ return -EINVAL; + + proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL); + if (!proclk) +@@ -115,6 +135,7 @@ static int clk_hifiberry_dacpro_probe(st + + proclk->mode = 0; + proclk->hw.init = &init; ++ memcpy(&proclk->clk_rates, of_id->data, sizeof(proclk->clk_rates)); + + clk = devm_clk_register(dev, &proclk->hw); + if (!IS_ERR(clk)) { +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -271,6 +271,7 @@ config SND_BCM2708_SOC_ALLO_BOSS_DAC + tristate "Support for Allo Boss DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x_I2C ++ select COMMON_CLK_HIFIBERRY_DACPRO + help + Say Y or M if you want to add support for Allo Boss DAC. + diff --git a/target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch b/target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch new file mode 100644 index 0000000000..22bca6c7f4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch @@ -0,0 +1,21 @@ +From 2addf7045f2b4866ab819f48e4d32f5734a32134 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Thu, 20 Jul 2023 15:15:27 +0100 +Subject: [PATCH] fixup! drm/tc358762: Set the pre_enable_upstream_first flag + to configure DSI host + +--- + drivers/gpu/drm/bridge/tc358762.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/bridge/tc358762.c ++++ b/drivers/gpu/drm/bridge/tc358762.c +@@ -229,7 +229,7 @@ static int tc358762_probe(struct mipi_ds + ctx->bridge.funcs = &tc358762_bridge_funcs; + ctx->bridge.type = DRM_MODE_CONNECTOR_DPI; + ctx->bridge.of_node = dev->of_node; +- ctx->bridge.pre_enable_upstream_first = true; ++ ctx->bridge.pre_enable_prev_first = true; + + drm_bridge_add(&ctx->bridge); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch b/target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch new file mode 100644 index 0000000000..82a3c9ea5b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch @@ -0,0 +1,48 @@ +From b84b8a9ad2046a855a7044b6368def01ddd5de6e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 21 Jul 2023 16:50:56 +0100 +Subject: [PATCH] rpi sound cards: Fix Codec Zero rate switching + +The Raspberry Pi Codec Zero (and IQaudIO Codec) don't notify the DA7213 +codec when it needs to change PLL frequencies. As a result, audio can +be played at the wrong rate - play a 48kHz sound immediately after a +44.1kHz sound to see the effect, but in some configurations the codec +can lock into the wrong state and always get some rates wrong. + +Add the necessary notification to fix the issue. + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/iqaudio-codec.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/sound/soc/bcm/iqaudio-codec.c ++++ b/sound/soc/bcm/iqaudio-codec.c +@@ -143,6 +143,7 @@ static int snd_rpi_iqaudio_codec_hw_para + struct snd_pcm_hw_params *params) + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int samplerate = params_rate(params); + + switch (samplerate) { +@@ -152,15 +153,17 @@ static int snd_rpi_iqaudio_codec_hw_para + case 48000: + case 96000: + pll_out = DA7213_PLL_FREQ_OUT_98304000; +- return 0; ++ break; + case 44100: + case 88200: + pll_out = DA7213_PLL_FREQ_OUT_90316800; +- return 0; ++ break; + default: + dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate); + return -EINVAL; + } ++ ++ return snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0, pll_out); + } + + static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = { diff --git a/target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch b/target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch new file mode 100644 index 0000000000..0539b19cf5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch @@ -0,0 +1,68 @@ +From 31822340129e3c4030500d7f30ce4d19bbf9dd40 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 24 Jul 2023 17:34:47 +0100 +Subject: [PATCH] overlays: Add trickle-voltage-mv parameter to RTCs + +The RV3032 RTC requires an additional DT property to enable trickle +charging. Add a parameter - trickle-voltage-mv - to the i2c-rtc +and i2c-rtc-gpio overlays to set it. + +See: https://github.com/raspberrypi/linux/issues/5547 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 12 ++++++++---- + arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi | 2 ++ + 2 files changed, 10 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1957,13 +1957,15 @@ Params: abx80x Select o + "schottky" (ABx80x and RV1805 only) + + trickle-resistor-ohms Resistor value for trickle charge (DS1339, +- ABx80x, RV1805, RV3028) ++ ABx80x, BQ32000, RV1805, RV3028, RV3032) ++ ++ trickle-voltage-mv Charge pump voltage for trickle charge (RV3032) + + wakeup-source Specify that the RTC can be used as a wakeup + source + + backup-switchover-mode Backup power supply switch mode. Must be 0 for +- off or 1 for Vdd < VBackup (RV3028 only) ++ off or 1 for Vdd < VBackup (RV3028, RV3032) + + + Name: i2c-rtc-gpio +@@ -2027,13 +2029,15 @@ Params: abx80x Select o + "schottky" (ABx80x and RV1805 only) + + trickle-resistor-ohms Resistor value for trickle charge (DS1339, +- ABx80x, RV1805, RV3028) ++ ABx80x, BQ32000, RV1805, RV3028, RV3032) ++ ++ trickle-voltage-mv Charge pump voltage for trickle charge (RV3032) + + wakeup-source Specify that the RTC can be used as a wakeup + source + + backup-switchover-mode Backup power supply switch mode. Must be 0 for +- off or 1 for Vdd < VBackup (RV3028 only) ++ off or 1 for Vdd < VBackup (RV3028, RV3032) + + i2c_gpio_sda GPIO used for I2C data (default "23") + +--- a/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi ++++ b/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi +@@ -339,8 +339,10 @@ + <&ds1340>,"trickle-resistor-ohms:0", + <&abx80x>,"abracon,tc-resistor:0", + <&rv3028>,"trickle-resistor-ohms:0", ++ <&rv3032>,"trickle-resistor-ohms:0", + <&rv1805>,"abracon,tc-resistor:0", + <&bq32000>,"abracon,tc-resistor:0"; ++ trickle-voltage-mv = <&rv3032>,"trickle-voltage-millivolts:0"; + backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0"; + wakeup-source = <&ds1339>,"wakeup-source?", + <&ds3231>,"wakeup-source?", diff --git a/target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch b/target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch new file mode 100644 index 0000000000..f10c0f03b5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch @@ -0,0 +1,25 @@ +From 5fb3b300557d6a6902e7321f42fdabb8c09eef54 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Fri, 28 Jul 2023 12:00:40 +0100 +Subject: [PATCH] drivers: media: imx296: Add standby delay during probe + +Add a 2-5ms delay when coming out of standby and before reading the +sensor info register durning probe, as instructed by the datasheet. This +standby delay is already present when the sensor starts streaming. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx296.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/media/i2c/imx296.c ++++ b/drivers/media/i2c/imx296.c +@@ -1022,6 +1022,8 @@ static int imx296_identify_model(struct + return ret; + } + ++ usleep_range(2000, 5000); ++ + ret = imx296_read(sensor, IMX296_SENSOR_INFO); + if (ret < 0) { + dev_err(sensor->dev, "failed to read sensor information (%d)\n", diff --git a/target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch b/target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch new file mode 100644 index 0000000000..535511eb93 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch @@ -0,0 +1,78 @@ +From e1016d61e3dcb058932e8ec5072f2c4bbb05fcb7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Sun, 30 Jul 2023 18:27:03 +0100 +Subject: [PATCH] overlays: Add bmp380 to i2c-sensor overlay + +Add support for the BMP380 pressor sensor to the i2c-sensor overlay. + +See: https://github.com/raspberrypi/linux/issues/5558 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 7 +++++-- + .../boot/dts/overlays/i2c-sensor-common.dtsi | 19 ++++++++++++++++++- + 2 files changed, 23 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2052,8 +2052,8 @@ Info: Adds support for a number of I2C + light level and chemical sensors on i2c_arm + Load: dtoverlay=i2c-sensor,= + Params: addr Set the address for the BH1750, BME280, BME680, +- BMP280, CCS811, DS1621, HDC100X, JC42, LM75, +- MCP980x, MPU6050, MPU9250, MS5637, MS5803, ++ BMP280, BMP380, CCS811, DS1621, HDC100X, JC42, ++ LM75, MCP980x, MPU6050, MPU9250, MS5637, MS5803, + MS5805, MS5837, MS8607, SHT3x or TMP102 + + aht10 Select the Aosong AHT10 temperature and humidity +@@ -2075,6 +2075,9 @@ Params: addr Set the + bmp280 Select the Bosch Sensortronic BMP280 + Valid addresses 0x76-0x77, default 0x76 + ++ bmp380 Select the Bosch Sensortronic BMP380 ++ Valid addresses 0x76-0x77, default 0x76 ++ + bno055 Select the Bosch Sensortronic BNO055 IMU + Valid address 0x28-0x29, default 0x29 + +--- a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi +@@ -493,11 +493,27 @@ + }; + }; + ++ fragment@33 { ++ target = <&i2cbus>; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ bmp380: bmp380@76 { ++ compatible = "bosch,bmp380"; ++ reg = <0x76>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ + __overrides__ { + bme280 = <0>,"+0"; + bmp085 = <0>,"+1"; + bmp180 = <0>,"+2"; + bmp280 = <0>,"+3"; ++ bmp380 = <0>,"+33"; + htu21 = <0>,"+4"; + lm75 = <0>,"+5"; + lm75addr = <&lm75>,"reg:0"; +@@ -535,7 +551,8 @@ + <&ms5637>,"reg:0", <&ms5803>,"reg:0", <&ms5805>,"reg:0", + <&ms5837>,"reg:0", <&ms8607>,"reg:0", + <&mpu6050>,"reg:0", <&mpu9250>,"reg:0", +- <&bno055>,"reg:0", <&sht4x>,"reg:0"; ++ <&bno055>,"reg:0", <&sht4x>,"reg:0", ++ <&bmp380>,"reg:0"; + int_pin = <&max30102>, "interrupts:0", + <&mpu6050>, "interrupts:0", + <&mpu9250>, "interrupts:0"; diff --git a/target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch b/target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch new file mode 100644 index 0000000000..d5cce9a433 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch @@ -0,0 +1,162 @@ +From 4b729a06b15fc5ee3694dcc62346dcb718ae4290 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Sun, 26 Mar 2023 13:59:11 +0200 +Subject: [PATCH] can: isotp: add module parameter for maximum pdu size + +commit 96d1c81e6a0478535342dff6c730adb076cd84e8 upstream. + +With ISO 15765-2:2016 the PDU size is not limited to 2^12 - 1 (4095) +bytes but can be represented as a 32 bit unsigned integer value which +allows 2^32 - 1 bytes (~4GB). The use-cases like automotive unified +diagnostic services (UDS) and flashing of ECUs still use the small +static buffers which are provided at socket creation time. + +When a use-case requires to transfer PDUs up to 1025 kByte the maximum +PDU size can now be extended by setting the module parameter +max_pdu_size. The extended size buffers are only allocated on a +per-socket/connection base when needed at run-time. + +changes since v2: https://lore.kernel.org/all/20230313172510.3851-1-socketcan@hartkopp.net +- use ARRAY_SIZE() to reference DEFAULT_MAX_PDU_SIZE only at one place + +changes since v1: https://lore.kernel.org/all/20230311143446.3183-1-socketcan@hartkopp.net +- limit the minimum 'max_pdu_size' to 4095 to maintain the classic + behavior before ISO 15765-2:2016 + +Link: https://github.com/raspberrypi/linux/issues/5371 +Signed-off-by: Oliver Hartkopp +Link: https://lore.kernel.org/all/20230326115911.15094-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +--- + net/can/isotp.c | 65 ++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 56 insertions(+), 9 deletions(-) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -85,10 +85,21 @@ MODULE_ALIAS("can-proto-6"); + + /* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can + * take full 32 bit values (4 Gbyte). We would need some good concept to handle +- * this between user space and kernel space. For now increase the static buffer +- * to something about 64 kbyte to be able to test this new functionality. ++ * this between user space and kernel space. For now set the static buffer to ++ * something about 8 kbyte to be able to test this new functionality. + */ +-#define MAX_MSG_LENGTH 66000 ++#define DEFAULT_MAX_PDU_SIZE 8300 ++ ++/* maximum PDU size before ISO 15765-2:2016 extension was 4095 */ ++#define MAX_12BIT_PDU_SIZE 4095 ++ ++/* limit the isotp pdu size from the optional module parameter to 1MByte */ ++#define MAX_PDU_SIZE (1025 * 1024U) ++ ++static unsigned int max_pdu_size __read_mostly = DEFAULT_MAX_PDU_SIZE; ++module_param(max_pdu_size, uint, 0444); ++MODULE_PARM_DESC(max_pdu_size, "maximum isotp pdu size (default " ++ __stringify(DEFAULT_MAX_PDU_SIZE) ")"); + + /* N_PCI type values in bits 7-4 of N_PCI bytes */ + #define N_PCI_SF 0x00 /* single frame */ +@@ -124,13 +135,15 @@ enum { + }; + + struct tpcon { +- unsigned int idx; ++ u8 *buf; ++ unsigned int buflen; + unsigned int len; ++ unsigned int idx; + u32 state; + u8 bs; + u8 sn; + u8 ll_dl; +- u8 buf[MAX_MSG_LENGTH + 1]; ++ u8 sbuf[DEFAULT_MAX_PDU_SIZE]; + }; + + struct isotp_sock { +@@ -498,7 +511,17 @@ static int isotp_rcv_ff(struct sock *sk, + if (so->rx.len + ae + off + ff_pci_sz < so->rx.ll_dl) + return 1; + +- if (so->rx.len > MAX_MSG_LENGTH) { ++ /* PDU size > default => try max_pdu_size */ ++ if (so->rx.len > so->rx.buflen && so->rx.buflen < max_pdu_size) { ++ u8 *newbuf = kmalloc(max_pdu_size, GFP_ATOMIC); ++ ++ if (newbuf) { ++ so->rx.buf = newbuf; ++ so->rx.buflen = max_pdu_size; ++ } ++ } ++ ++ if (so->rx.len > so->rx.buflen) { + /* send FC frame with overflow status */ + isotp_send_fc(sk, ae, ISOTP_FC_OVFLW); + return 1; +@@ -802,7 +825,7 @@ static void isotp_create_fframe(struct c + cf->data[0] = so->opt.ext_address; + + /* create N_PCI bytes with 12/32 bit FF_DL data length */ +- if (so->tx.len > 4095) { ++ if (so->tx.len > MAX_12BIT_PDU_SIZE) { + /* use 32 bit FF_DL notation */ + cf->data[ae] = N_PCI_FF; + cf->data[ae + 1] = 0; +@@ -939,7 +962,17 @@ static int isotp_sendmsg(struct socket * + goto err_event_drop; + } + +- if (!size || size > MAX_MSG_LENGTH) { ++ /* PDU size > default => try max_pdu_size */ ++ if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) { ++ u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL); ++ ++ if (newbuf) { ++ so->tx.buf = newbuf; ++ so->tx.buflen = max_pdu_size; ++ } ++ } ++ ++ if (!size || size > so->tx.buflen) { + err = -EINVAL; + goto err_out_drop; + } +@@ -1194,6 +1227,12 @@ static int isotp_release(struct socket * + so->ifindex = 0; + so->bound = 0; + ++ if (so->rx.buf != so->rx.sbuf) ++ kfree(so->rx.buf); ++ ++ if (so->tx.buf != so->tx.sbuf) ++ kfree(so->tx.buf); ++ + sock_orphan(sk); + sock->sk = NULL; + +@@ -1588,6 +1627,11 @@ static int isotp_init(struct sock *sk) + so->rx.state = ISOTP_IDLE; + so->tx.state = ISOTP_IDLE; + ++ so->rx.buf = so->rx.sbuf; ++ so->tx.buf = so->tx.sbuf; ++ so->rx.buflen = ARRAY_SIZE(so->rx.sbuf); ++ so->tx.buflen = ARRAY_SIZE(so->tx.sbuf); ++ + hrtimer_init(&so->rxtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); + so->rxtimer.function = isotp_rx_timer_handler; + hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); +@@ -1670,7 +1714,10 @@ static __init int isotp_module_init(void + { + int err; + +- pr_info("can: isotp protocol\n"); ++ max_pdu_size = max_t(unsigned int, max_pdu_size, MAX_12BIT_PDU_SIZE); ++ max_pdu_size = min_t(unsigned int, max_pdu_size, MAX_PDU_SIZE); ++ ++ pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size); + + err = can_proto_register(&isotp_can_proto); + if (err < 0) diff --git a/target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch b/target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch new file mode 100644 index 0000000000..ee4079cd64 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch @@ -0,0 +1,40 @@ +From e1b03ea9e84320e6bf36a1486abaebbceadd7fc7 Mon Sep 17 00:00:00 2001 +From: Ben Benson +Date: Fri, 21 Jul 2023 15:59:51 +0100 +Subject: [PATCH] drivers: media: imx296: Updated imx296 driver for external + trigger + +Updated imx296 driver to support external trigger mode via XTR pin. +Added module parameter to control this mode. + +Signed-off-by: Ben Benson +--- + drivers/media/i2c/imx296.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/media/i2c/imx296.c ++++ b/drivers/media/i2c/imx296.c +@@ -20,6 +20,10 @@ + #include + #include + ++static int trigger_mode; ++module_param(trigger_mode, int, 0644); ++MODULE_PARM_DESC(trigger_mode, "Set trigger mode: 0=default, 1=XTRIG"); ++ + #define IMX296_PIXEL_ARRAY_WIDTH 1456 + #define IMX296_PIXEL_ARRAY_HEIGHT 1088 + +@@ -645,6 +649,12 @@ static int imx296_stream_on(struct imx29 + + imx296_write(sensor, IMX296_CTRL00, 0, &ret); + usleep_range(2000, 5000); ++ ++ if (trigger_mode == 1) { ++ imx296_write(sensor, IMX296_CTRL0B, IMX296_CTRL0B_TRIGEN, &ret); ++ imx296_write(sensor, IMX296_LOWLAGTRG, IMX296_LOWLAGTRG_FAST, &ret); ++ } ++ + imx296_write(sensor, IMX296_CTRL0A, 0, &ret); + + /* vflip and hflip cannot change during streaming */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch b/target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch new file mode 100644 index 0000000000..f45b68f154 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch @@ -0,0 +1,26 @@ +From 74bc238e86e62109c74d8f229dc105bf3818b4a7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 2 Aug 2023 14:35:32 +0100 +Subject: [PATCH] media: dt-bindings: imx258: Fix alternate compatible strings + +Multiple compatible strings must appear as an enum. + +Signed-off-by: Phil Elwell +--- + Documentation/devicetree/bindings/media/i2c/imx258.yaml | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/media/i2c/imx258.yaml ++++ b/Documentation/devicetree/bindings/media/i2c/imx258.yaml +@@ -19,8 +19,9 @@ description: |- + + properties: + compatible: +- const: sony,imx258 +- const: sony,imx258-pdaf ++ enum: ++ - sony,imx258 ++ - sony,imx258-pdaf + + assigned-clocks: true + assigned-clock-parents: true diff --git a/target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch b/target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch new file mode 100644 index 0000000000..43283784dd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch @@ -0,0 +1,21 @@ +From 282819aead0166af415b780241dc2def4caee7f4 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +Date: Mon, 3 Jul 2023 18:12:01 +0000 +Subject: [PATCH] char: broadcom: vc_mem: Fix preprocessor conditional + +Signed-off-by: Alexander Winkowski +--- + drivers/char/broadcom/vc_mem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/char/broadcom/vc_mem.c ++++ b/drivers/char/broadcom/vc_mem.c +@@ -353,7 +353,7 @@ vc_mem_exit(void) + pr_debug("%s: called\n", __func__); + + if (vc_mem_inited) { +-#if CONFIG_DEBUG_FS ++#ifdef CONFIG_DEBUG_FS + vc_mem_debugfs_deinit(); + #endif + device_destroy(vc_mem_class, vc_mem_devnum); diff --git a/target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch b/target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch new file mode 100644 index 0000000000..fe74c75e07 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch @@ -0,0 +1,32 @@ +From ec61075a786c455444a1d5df338a41bacfce0bb1 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +Date: Mon, 3 Jul 2023 18:23:02 +0000 +Subject: [PATCH] drivers: dwc_otg: Fix fallthrough warnings + +Signed-off-by: Alexander Winkowski +--- + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 1 + + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -2049,6 +2049,7 @@ int fiq_fsm_queue_split_transaction(dwc_ + } else { + st->fsm = FIQ_PER_SSPLIT_QUEUED; + } ++ break; + default: + break; + } +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -402,7 +402,7 @@ int32_t dwc_otg_hcd_handle_rx_status_q_l + hc->xfer_count += grxsts.b.bcnt; + hc->xfer_buff += grxsts.b.bcnt; + } +- ++ break; + case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: + case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + case DWC_GRXSTS_PKTSTS_CH_HALTED: diff --git a/target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch b/target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch new file mode 100644 index 0000000000..edd117c9b5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch @@ -0,0 +1,61 @@ +From 2dd2f36d10961e3819ff0525ae2567e601973826 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +Date: Mon, 3 Jul 2023 18:29:37 +0000 +Subject: [PATCH] vc04_services/vc-sm-cma: Switch one-bit bitfields to bool + +Clang 16 warns: + +../drivers/staging/vc04_services/vc-sm-cma/vc_sm.c:816:19: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion] + buffer->imported = 1; + ^ ~ +../drivers/staging/vc04_services/vc-sm-cma/vc_sm.c:822:17: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion] + buffer->in_use = 1; + ^ ~ +2 warnings generated. + +Signed-off-by: Alexander Winkowski +--- + drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 6 +++--- + drivers/staging/vc04_services/vc-sm-cma/vc_sm.h | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c ++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c +@@ -533,7 +533,7 @@ static void vc_sm_dma_buf_release(struct + + pr_debug("%s dmabuf %p, buffer %p\n", __func__, dmabuf, buffer); + +- buffer->in_use = 0; ++ buffer->in_use = false; + + /* Unmap on the VPU */ + vc_sm_vpu_free(buffer); +@@ -813,13 +813,13 @@ vc_sm_cma_import_dmabuf_internal(struct + buffer->size = import.size; + buffer->vpu_state = VPU_MAPPED; + +- buffer->imported = 1; ++ buffer->imported = true; + buffer->import.dma_buf = dma_buf; + + buffer->import.attach = attach; + buffer->import.sgt = sgt; + buffer->dma_addr = dma_addr; +- buffer->in_use = 1; ++ buffer->in_use = true; + buffer->kernel_id = import.kernel_id; + + /* +--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h ++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h +@@ -57,8 +57,8 @@ struct vc_sm_buffer { + + char name[VC_SM_MAX_NAME_LEN]; + +- int in_use:1; /* Kernel is still using this resource */ +- int imported:1; /* Imported dmabuf */ ++ bool in_use:1; /* Kernel is still using this resource */ ++ bool imported:1; /* Imported dmabuf */ + + enum vc_sm_vpu_mapping_state vpu_state; + u32 vc_handle; /* VideoCore handle for this buffer */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch b/target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch new file mode 100644 index 0000000000..d6fd3a9f92 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch @@ -0,0 +1,21 @@ +From 3333d45347d313ea589b8b8da1193d342060a946 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +Date: Mon, 3 Jul 2023 18:36:45 +0000 +Subject: [PATCH] media: i2c: ov2311: Fix uninitialized variable usage + +Signed-off-by: Alexander Winkowski +--- + drivers/media/i2c/ov2311.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/i2c/ov2311.c ++++ b/drivers/media/i2c/ov2311.c +@@ -1018,7 +1018,7 @@ static int ov2311_check_sensor_id(struct + struct i2c_client *client) + { + struct device *dev = &ov2311->client->dev; +- u32 id = 0, id_msb; ++ u32 id = 0, id_msb = 0; + int ret; + + ret = ov2311_read_reg(client, OV2311_REG_CHIP_ID + 1, diff --git a/target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch b/target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch new file mode 100644 index 0000000000..035b5b0049 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch @@ -0,0 +1,29 @@ +From e89e7655a197d28df49da2be7e2003436cf52197 Mon Sep 17 00:00:00 2001 +From: Ignacio Larrain +Date: Tue, 22 Aug 2023 11:11:56 -0400 +Subject: [PATCH] drm/panel: Fix default values for Waveshare 7.9 inch DSI + touchscreen (#5565) + +This fixes touchscreen calibration, axis swapping and inversion. + +As referenced in https://github.com/raspberrypi/linux/issues/5550 +--- + .../dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts +@@ -93,10 +93,10 @@ + <&touch>, "touchscreen-size-x:0=800", + <&touch>, "touchscreen-size-y:0=480"; + 7_9_inch = <&panel>, "compatible=waveshare,7.9inch-panel", +- <&touch>, "touchscreen-size-x:0=400", +- <&touch>, "touchscreen-size-y:0=1280", ++ <&touch>, "touchscreen-size-x:0=4096", ++ <&touch>, "touchscreen-size-y:0=4096", + <&touch>, "touchscreen-inverted-x?", +- <&touch>, "touchscreen-inverted-y?"; ++ <&touch>, "touchscreen-swapped-x-y?"; + 8_0_inch = <&panel>, "compatible=waveshare,8.0inch-panel", + <&touch>, "touchscreen-size-x:0=800", + <&touch>, "touchscreen-size-y:0=1280", diff --git a/target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch b/target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch new file mode 100644 index 0000000000..cf703b0029 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch @@ -0,0 +1,102 @@ +From 3fa2fbb7f6e60b85086e454403c5eab1af63b1aa Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 14 Jun 2023 13:43:58 +0100 +Subject: [PATCH] dtoverlays: Add i2c bus overrides to edt-ft5406 overlay + +Adds the option for the touch controller to be connected to any +of the I2C ports. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 17 +++++++++++++++- + .../boot/dts/overlays/edt-ft5406-overlay.dts | 20 +++++++++++++++++++ + arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 9 ++++++++- + 3 files changed, 44 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1040,9 +1040,11 @@ Params: dr_mode Dual rol + + + Name: edt-ft5406 +-Info: Overlay for the EDT FT5406 touchscreen on the CSI/DSI I2C interface. ++Info: Overlay for the EDT FT5406 touchscreen. + This works with the Raspberry Pi 7" touchscreen when not being polled + by the firmware. ++ By default the overlay uses the i2c_csi_dsi I2C interface, but this ++ can be overridden + You MUST use either "disable_touchscreen=1" or "ignore_lcd=1" in + config.txt to stop the firmware polling the touchscreen. + Load: dtoverlay=edt-ft5406,= +@@ -1051,6 +1053,19 @@ Params: sizex Touchscr + invx Touchscreen inverted x axis + invy Touchscreen inverted y axis + swapxy Touchscreen swapped x y axis ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c1 Choose the I2C1 bus on GPIOs 2&3 ++ i2c3 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c4 Choose the I2C4 bus (configure with the i2c4 ++ overlay - BCM2711 only) ++ i2c5 Choose the I2C5 bus (configure with the i2c5 ++ overlay - BCM2711 only) ++ i2c6 Choose the I2C6 bus (configure with the i2c6 ++ overlay - BCM2711 only) ++ addr Sets the address for the touch controller. Note ++ that the device must be configured to use the ++ specified address. + + + Name: enc28j60 +--- a/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts ++++ b/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts +@@ -23,4 +23,24 @@ + status = "okay"; + }; + }; ++ ++ __overrides__ { ++ i2c0 = <&frag13>,"target:0=",<&i2c0>; ++ i2c1 = <&frag13>, "target?=0", ++ <&frag13>, "target-path=i2c1", ++ <0>,"-0-1"; ++ i2c3 = <&frag13>, "target?=0", ++ <&frag13>, "target-path=i2c3", ++ <0>,"-0-1"; ++ i2c4 = <&frag13>, "target?=0", ++ <&frag13>, "target-path=i2c4", ++ <0>,"-0-1"; ++ i2c5 = <&frag13>, "target?=0", ++ <&frag13>, "target-path=i2c5", ++ <0>,"-0-1"; ++ i2c6 = <&frag13>, "target?=0", ++ <&frag13>, "target-path=i2c6", ++ <0>,"-0-1"; ++ addr = <&ft5406>,"reg:0"; ++ }; + }; +--- a/arch/arm/boot/dts/overlays/edt-ft5406.dtsi ++++ b/arch/arm/boot/dts/overlays/edt-ft5406.dtsi +@@ -23,7 +23,7 @@ + }; + + fragment@12 { +- target = <&i2c_csi_dsi>; ++ target = <&i2cbus>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; +@@ -37,6 +37,13 @@ + }; + }; + ++ frag13: fragment@13 { ++ target = <&i2c_csi_dsi>; ++ i2cbus: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + sizex = <&ft5406>,"touchscreen-size-x:0"; + sizey = <&ft5406>,"touchscreen-size-y:0"; diff --git a/target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch b/target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch new file mode 100644 index 0000000000..23953c9636 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch @@ -0,0 +1,25 @@ +From 9d9586dc0c0deecb90675bd70862fe262f7376ab Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 14 Jun 2023 14:25:21 +0100 +Subject: [PATCH] dtoverlays: Fix README text for i2c-fan + +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 +@@ -1800,10 +1800,10 @@ Params: addr Sets the + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + +- i2c4 Choose the I2C3 bus (configure with the i2c3 ++ i2c4 Choose the I2C4 bus (configure with the i2c4 + overlay - BCM2711 only) + +- i2c5 Choose the I2C5 bus (configure with the i2c4 ++ i2c5 Choose the I2C5 bus (configure with the i2c5 + overlay - BCM2711 only) + + i2c6 Choose the I2C6 bus (configure with the i2c6 diff --git a/target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch b/target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch new file mode 100644 index 0000000000..48e2fcdc74 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch @@ -0,0 +1,50 @@ +From e804bd1843236a63815e9acfb1a38ebf9a28ef5b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 31 Aug 2023 16:45:44 +0100 +Subject: [PATCH] drivers: irqchip: irq-bcm2835: Concurrency fix + +The commit shown in Fixes: aims to improve interrupt throughput by +getting the handlers invoked on different CPU cores. It does so (*) by +using an irq_ack hook to change the interrupt routing. + +Unfortunately, the IRQ status bits must be cleared at source, which only +happens once the interrupt handler has run - there is no easy way for +one core to claim one of the IRQs before sending the remainder to the +next core on the list, so waking another core immediately results in a +race with a chance of both cores handling the same IRQ. It is probably +for this reason that the routing change is deferred to irq_ack, but that +doesn't guarantee no clashes - after irq_ack is called, control returns +to bcm2836_chained_handler_irq which proceeds to check for other pending +IRQs at a time when the next core is probably doing the same thing. + +Since the whole point of the original commit is to distribute the IRQ +handling, there is no reason to attempt to handle multiple IRQs in one +interrupt callback, so the problem can be solved (or at least made much +harder to reproduce) by changing a "while" into an "if", so that each +invocation only handles one IRQ. + +(*) I'm not convinced it's as effective as claimed since irq_ack is +called _after_ the interrupt handler, but the author thought it made a +difference. + +See: https://github.com/raspberrypi/linux/issues/5214 + https://github.com/raspberrypi/linux/pull/1794 + +Fixes: fd4c9785bde8 ("ARM64: Round-Robin dispatch IRQs between CPUs.") +Signed-off-by: Phil Elwell +--- + drivers/irqchip/irq-bcm2835.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/irqchip/irq-bcm2835.c ++++ b/drivers/irqchip/irq-bcm2835.c +@@ -343,7 +343,8 @@ static void bcm2836_chained_handle_irq(s + { + u32 hwirq; + +- while ((hwirq = get_next_armctrl_hwirq()) != ~0) ++ hwirq = get_next_armctrl_hwirq(); ++ if (hwirq != ~0) + generic_handle_domain_irq(intc.domain, hwirq); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch b/target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch new file mode 100644 index 0000000000..10b1f15d2c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch @@ -0,0 +1,58 @@ +From 5e54398e1b61335883dff1be46a6c8b3ca973926 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 30 Aug 2023 18:03:37 +0100 +Subject: [PATCH] dtoverlays: Add drm option to piscreen overlay + +Adds the option of selecting the DRM/KMS TinyDRM driver for +this panel, rather than the deprecated FBTFT one. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 3 +++ + arch/arm/boot/dts/overlays/piscreen-overlay.dts | 10 +++++++--- + 2 files changed, 10 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3245,6 +3245,9 @@ Params: speed Display + + xohms Touchpanel sensitivity (X-plate resistance) + ++ drm Select the DRM/KMS driver instead of the FBTFT ++ one ++ + + Name: piscreen2r + Info: PiScreen 2 with resistive TP display by OzzMaker.com +--- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts ++++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts +@@ -6,6 +6,8 @@ + /dts-v1/; + /plugin/; + ++#include ++ + / { + compatible = "brcm,bcm2835"; + +@@ -59,9 +61,9 @@ + fps = <30>; + buswidth = <8>; + regwidth = <16>; +- reset-gpios = <&gpio 25 1>; +- dc-gpios = <&gpio 24 0>; +- led-gpios = <&gpio 22 0>; ++ reset-gpios = <&gpio 25 GPIO_ACTIVE_LOW>; ++ dc-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>; ++ led-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; + debug = <0>; + + init = <0x10000b0 0x00 +@@ -98,5 +100,7 @@ + fps = <&piscreen>,"fps:0"; + debug = <&piscreen>,"debug:0"; + xohms = <&piscreen_ts>,"ti,x-plate-ohms;0"; ++ drm = <&piscreen>,"compatible=waveshare,rpi-lcd-35", ++ <&piscreen>,"reset-gpios:8=",; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch b/target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch new file mode 100644 index 0000000000..0bce9f9e78 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch @@ -0,0 +1,36 @@ +From f59fe2d1bd056af117eb512bb0e9210a943c6d47 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 1 Sep 2023 12:17:38 +0100 +Subject: [PATCH] drm/ili9486: Resolve clash in spi_device_id names + +For "Really Good Reasons" [1] the SPI core requires a match +between compatible device strings and the name in spi_device_id. + +The ili9486 driver uses compatible strings "waveshare,rpi-lcd-35" +and "ozzmaker,piscreen", but "rpi-lcd-35" and "piscreen" are missing, +so add them. + +Compatible string "ilitek,ili9486" is already used by +staging/fbtft/fb_ili9486, therefore leaving it present in ili9486 as an +spi_device_id causes the incorrect module to be loaded, therefore remove +this id. + +[1] https://elixir.bootlin.com/linux/latest/source/drivers/spi/spi.c#L487 + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/tiny/ili9486.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/tiny/ili9486.c ++++ b/drivers/gpu/drm/tiny/ili9486.c +@@ -187,7 +187,8 @@ static const struct of_device_id ili9486 + MODULE_DEVICE_TABLE(of, ili9486_of_match); + + static const struct spi_device_id ili9486_id[] = { +- { "ili9486", 0 }, ++ { "rpi-lcd-35", 0 }, ++ { "piscreen", 0 }, + { } + }; + MODULE_DEVICE_TABLE(spi, ili9486_id); diff --git a/target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch b/target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch new file mode 100644 index 0000000000..71f1063986 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch @@ -0,0 +1,50 @@ +From 50c5a8558f4aaa54a3c4f5a8c2b6053f641d94eb Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 1 Sep 2023 12:23:30 +0100 +Subject: [PATCH] input: ads7846: Add missing spi_device_id strings + +The SPI core logs error messages if a compatible string device +name is not also present as an spi_device_id. + +No spi_device_id values are specified by the driver, therefore +we get 4 log lines every time it is loaded: +SPI driver ads7846 has no spi_device_id for ti,tsc2046 +SPI driver ads7846 has no spi_device_id for ti,ads7843 +SPI driver ads7846 has no spi_device_id for ti,ads7845 +SPI driver ads7846 has no spi_device_id for ti,ads7873 + +Add the spi_device_id values for these devices. + +Signed-off-by: Dave Stevenson +--- + drivers/input/touchscreen/ads7846.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/input/touchscreen/ads7846.c ++++ b/drivers/input/touchscreen/ads7846.c +@@ -1127,6 +1127,17 @@ static const struct of_device_id ads7846 + }; + MODULE_DEVICE_TABLE(of, ads7846_dt_ids); + ++static const struct spi_device_id ads7846_spi_ids[] = { ++ { "tsc2046", 0 }, ++ { "ads7843", 0 }, ++ { "ads7843", 0 }, ++ { "ads7845", 0 }, ++ { "ads7846", 0 }, ++ { "ads7873", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(spi, ads7846_spi_ids); ++ + static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) + { + struct ads7846_platform_data *pdata; +@@ -1424,6 +1435,7 @@ static struct spi_driver ads7846_driver + .pm = &ads7846_pm, + .of_match_table = of_match_ptr(ads7846_dt_ids), + }, ++ .id_table = ads7846_spi_ids, + .probe = ads7846_probe, + .remove = ads7846_remove, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch b/target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch new file mode 100644 index 0000000000..5af23821a8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch @@ -0,0 +1,27 @@ +From 65742d7116e89b08858fcd7d67bd521ee19ee837 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 30 Aug 2023 18:05:43 +0100 +Subject: [PATCH] staging: bcm2835-codec: Downgrade the level for a debug + message + +The debug message from bcm2835_codec_buf_prepare when the buffer +size is incorrect can be a little spammy if the application isn't +careful on how it drives it, therefore drop the priority of the +message. + +Signed-off-by: Dave Stevenson +--- + .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c ++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +@@ -2883,7 +2883,7 @@ static int bcm2835_codec_buf_prepare(str + } + + if (vb2_plane_size(vb, 0) < q_data->sizeimage) { +- v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n", ++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), + (long)q_data->sizeimage); + return -EINVAL; diff --git a/target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch b/target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch new file mode 100644 index 0000000000..873077f51c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch @@ -0,0 +1,286 @@ +From cee471c3ada3215d6dfc53fb0f1b97548444dea7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 5 Sep 2023 11:56:19 +0100 +Subject: [PATCH] gpio-fsm: Sort functions into a more logical order + +Move some functions into a more logical ordering. This change causes +no functional change and is essentially cosmetic. + +Signed-off-by: Phil Elwell +--- + drivers/gpio/gpio-fsm.c | 245 ++++++++++++++++++++-------------------- + 1 file changed, 125 insertions(+), 120 deletions(-) + +--- a/drivers/gpio/gpio-fsm.c ++++ b/drivers/gpio/gpio-fsm.c +@@ -193,131 +193,14 @@ static void free_symbols(struct symtab_e + } + } + +-static int gpio_fsm_get_direction(struct gpio_chip *gc, unsigned int off) +-{ +- struct gpio_fsm *gf = gpiochip_get_data(gc); +- struct soft_gpio *sg; +- +- if (off >= gf->num_soft_gpios) +- return -EINVAL; +- sg = &gf->soft_gpios[off]; +- +- return sg->dir; +-} +- +-static int gpio_fsm_get(struct gpio_chip *gc, unsigned int off) +-{ +- struct gpio_fsm *gf = gpiochip_get_data(gc); +- struct soft_gpio *sg; +- +- if (off >= gf->num_soft_gpios) +- return -EINVAL; +- sg = &gf->soft_gpios[off]; +- +- return sg->value; +-} +- + static void gpio_fsm_go_to_state(struct gpio_fsm *gf, +- struct fsm_state *new_state) +-{ +- struct input_gpio_state *inp_state; +- struct gpio_event *gp_ev; +- struct fsm_state *state; +- int i; +- +- dev_dbg(gf->dev, "go_to_state(%s)\n", +- new_state ? new_state->name : ""); +- +- spin_lock(&gf->spinlock); +- +- if (gf->next_state) { +- /* Something else has already requested a transition */ +- spin_unlock(&gf->spinlock); +- return; +- } +- +- gf->next_state = new_state; +- state = gf->current_state; +- gf->delay_target_state = NULL; +- +- if (state) { +- /* Disarm any GPIO IRQs */ +- for (i = 0; i < state->num_gpio_events; i++) { +- gp_ev = &state->gpio_events[i]; +- inp_state = &gf->input_gpio_states[gp_ev->index]; +- inp_state->target = NULL; +- } +- } +- +- spin_unlock(&gf->spinlock); +- +- if (new_state) +- schedule_work(&gf->work); +-} ++ struct fsm_state *new_state); + + static void gpio_fsm_set_soft(struct gpio_fsm *gf, +- unsigned int off, int val) +-{ +- struct soft_gpio *sg = &gf->soft_gpios[off]; +- struct gpio_event *gp_ev; +- struct fsm_state *state; +- int i; +- +- dev_dbg(gf->dev, "set(%d,%d)\n", off, val); +- state = gf->current_state; +- sg->value = val; +- for (i = 0; i < state->num_soft_events; i++) { +- gp_ev = &state->soft_events[i]; +- if (gp_ev->index == off && gp_ev->value == val) { +- if (gf->debug) +- dev_info(gf->dev, +- "GF_SOFT %d->%d -> %s\n", gp_ev->index, +- gp_ev->value, gp_ev->target->name); +- gpio_fsm_go_to_state(gf, gp_ev->target); +- break; +- } +- } +-} +- +-static int gpio_fsm_direction_input(struct gpio_chip *gc, unsigned int off) +-{ +- struct gpio_fsm *gf = gpiochip_get_data(gc); +- struct soft_gpio *sg; +- +- if (off >= gf->num_soft_gpios) +- return -EINVAL; +- sg = &gf->soft_gpios[off]; +- sg->dir = GPIOF_DIR_IN; +- +- return 0; +-} +- +-static int gpio_fsm_direction_output(struct gpio_chip *gc, unsigned int off, +- int value) +-{ +- struct gpio_fsm *gf = gpiochip_get_data(gc); +- struct soft_gpio *sg; +- +- if (off >= gf->num_soft_gpios) +- return -EINVAL; +- sg = &gf->soft_gpios[off]; +- sg->dir = GPIOF_DIR_OUT; +- gpio_fsm_set_soft(gf, off, value); +- +- return 0; +-} +- +-static void gpio_fsm_set(struct gpio_chip *gc, unsigned int off, int val) +-{ +- struct gpio_fsm *gf; +- +- gf = gpiochip_get_data(gc); +- if (off < gf->num_soft_gpios) +- gpio_fsm_set_soft(gf, off, val); +-} ++ unsigned int off, int val); + + static void gpio_fsm_enter_state(struct gpio_fsm *gf, +- struct fsm_state *state) ++ struct fsm_state *state) + { + struct input_gpio_state *inp_state; + struct output_signal *signal; +@@ -431,6 +314,44 @@ static void gpio_fsm_enter_state(struct + } + } + ++static void gpio_fsm_go_to_state(struct gpio_fsm *gf, ++ struct fsm_state *new_state) ++{ ++ struct input_gpio_state *inp_state; ++ struct gpio_event *gp_ev; ++ struct fsm_state *state; ++ int i; ++ ++ dev_dbg(gf->dev, "go_to_state(%s)\n", ++ new_state ? new_state->name : ""); ++ ++ spin_lock(&gf->spinlock); ++ ++ if (gf->next_state) { ++ /* Something else has already requested a transition */ ++ spin_unlock(&gf->spinlock); ++ return; ++ } ++ ++ gf->next_state = new_state; ++ state = gf->current_state; ++ gf->delay_target_state = NULL; ++ ++ if (state) { ++ /* Disarm any GPIO IRQs */ ++ for (i = 0; i < state->num_gpio_events; i++) { ++ gp_ev = &state->gpio_events[i]; ++ inp_state = &gf->input_gpio_states[gp_ev->index]; ++ inp_state->target = NULL; ++ } ++ } ++ ++ spin_unlock(&gf->spinlock); ++ ++ if (new_state) ++ schedule_work(&gf->work); ++} ++ + static void gpio_fsm_work(struct work_struct *work) + { + struct input_gpio_state *inp_state; +@@ -851,6 +772,90 @@ static int resolve_sym_to_state(struct g + return 0; + } + ++static void gpio_fsm_set_soft(struct gpio_fsm *gf, ++ unsigned int off, int val) ++{ ++ struct soft_gpio *sg = &gf->soft_gpios[off]; ++ struct gpio_event *gp_ev; ++ struct fsm_state *state; ++ int i; ++ ++ dev_dbg(gf->dev, "set(%d,%d)\n", off, val); ++ state = gf->current_state; ++ sg->value = val; ++ for (i = 0; i < state->num_soft_events; i++) { ++ gp_ev = &state->soft_events[i]; ++ if (gp_ev->index == off && gp_ev->value == val) { ++ if (gf->debug) ++ dev_info(gf->dev, ++ "GF_SOFT %d->%d -> %s\n", gp_ev->index, ++ gp_ev->value, gp_ev->target->name); ++ gpio_fsm_go_to_state(gf, gp_ev->target); ++ break; ++ } ++ } ++} ++ ++static int gpio_fsm_get(struct gpio_chip *gc, unsigned int off) ++{ ++ struct gpio_fsm *gf = gpiochip_get_data(gc); ++ struct soft_gpio *sg; ++ ++ if (off >= gf->num_soft_gpios) ++ return -EINVAL; ++ sg = &gf->soft_gpios[off]; ++ ++ return sg->value; ++} ++ ++static void gpio_fsm_set(struct gpio_chip *gc, unsigned int off, int val) ++{ ++ struct gpio_fsm *gf; ++ ++ gf = gpiochip_get_data(gc); ++ if (off < gf->num_soft_gpios) ++ gpio_fsm_set_soft(gf, off, val); ++} ++ ++static int gpio_fsm_get_direction(struct gpio_chip *gc, unsigned int off) ++{ ++ struct gpio_fsm *gf = gpiochip_get_data(gc); ++ struct soft_gpio *sg; ++ ++ if (off >= gf->num_soft_gpios) ++ return -EINVAL; ++ sg = &gf->soft_gpios[off]; ++ ++ return sg->dir; ++} ++ ++static int gpio_fsm_direction_input(struct gpio_chip *gc, unsigned int off) ++{ ++ struct gpio_fsm *gf = gpiochip_get_data(gc); ++ struct soft_gpio *sg; ++ ++ if (off >= gf->num_soft_gpios) ++ return -EINVAL; ++ sg = &gf->soft_gpios[off]; ++ sg->dir = GPIOF_DIR_IN; ++ ++ return 0; ++} ++ ++static int gpio_fsm_direction_output(struct gpio_chip *gc, unsigned int off, ++ int value) ++{ ++ struct gpio_fsm *gf = gpiochip_get_data(gc); ++ struct soft_gpio *sg; ++ ++ if (off >= gf->num_soft_gpios) ++ return -EINVAL; ++ sg = &gf->soft_gpios[off]; ++ sg->dir = GPIOF_DIR_OUT; ++ gpio_fsm_set_soft(gf, off, value); ++ ++ return 0; ++} + + /* + * /sys/class/gpio-fsm// diff --git a/target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch b/target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch new file mode 100644 index 0000000000..ae3c019e25 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch @@ -0,0 +1,192 @@ +From f0061ffc98c6e027c5774e2a24ceadcfee4167ea Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 5 Sep 2023 12:01:13 +0100 +Subject: [PATCH] gpio_fsm: Rework the atomic-vs-non-atomic split + +Partition the code to separate atomic and non-atomic methods so that +none of them have to handle both cases. The result avoids using deferred +work unless necessary, and should be easier to understand. + +Signed-off-by: Phil Elwell +--- + drivers/gpio/gpio-fsm.c | 84 ++++++++++++++++++++--------------------- + 1 file changed, 41 insertions(+), 43 deletions(-) + +--- a/drivers/gpio/gpio-fsm.c ++++ b/drivers/gpio/gpio-fsm.c +@@ -193,9 +193,6 @@ static void free_symbols(struct symtab_e + } + } + +-static void gpio_fsm_go_to_state(struct gpio_fsm *gf, +- struct fsm_state *new_state); +- + static void gpio_fsm_set_soft(struct gpio_fsm *gf, + unsigned int off, int val); + +@@ -213,6 +210,7 @@ static void gpio_fsm_enter_state(struct + dev_dbg(gf->dev, "enter_state(%s)\n", state->name); + + gf->current_state = state; ++ gf->delay_target_state = NULL; + + // 1. Apply any listed signals + for (i = 0; i < state->num_signals; i++) { +@@ -271,7 +269,7 @@ static void gpio_fsm_enter_state(struct + dev_info(gf->dev, + "GF_SOFT %d=%d -> %s\n", event->index, + event->value, event->target->name); +- gpio_fsm_go_to_state(gf, event->target); ++ gpio_fsm_enter_state(gf, event->target); + return; + } + } +@@ -284,7 +282,7 @@ static void gpio_fsm_enter_state(struct + inp_state->value = event->value; + inp_state->enabled = true; + +- value = gpiod_get_value(gf->input_gpios->desc[event->index]); ++ value = gpiod_get_value_cansleep(gf->input_gpios->desc[event->index]); + + // Clear stale event state + disable_irq(inp_state->irq); +@@ -299,7 +297,7 @@ static void gpio_fsm_enter_state(struct + dev_info(gf->dev, + "GF_IN %d=%d -> %s\n", event->index, + event->value, event->target->name); +- gpio_fsm_go_to_state(gf, event->target); ++ gpio_fsm_enter_state(gf, event->target); + return; + } + } +@@ -325,6 +323,33 @@ static void gpio_fsm_go_to_state(struct + dev_dbg(gf->dev, "go_to_state(%s)\n", + new_state ? new_state->name : ""); + ++ state = gf->current_state; ++ ++ /* Disable any enabled GPIO IRQs */ ++ for (i = 0; i < state->num_gpio_events; i++) { ++ gp_ev = &state->gpio_events[i]; ++ inp_state = &gf->input_gpio_states[gp_ev->index]; ++ if (inp_state->enabled) { ++ inp_state->enabled = false; ++ irq_set_irq_type(inp_state->irq, ++ IRQF_TRIGGER_NONE); ++ } ++ } ++ ++ gpio_fsm_enter_state(gf, new_state); ++} ++ ++static void gpio_fsm_go_to_state_deferred(struct gpio_fsm *gf, ++ struct fsm_state *new_state) ++{ ++ struct input_gpio_state *inp_state; ++ struct gpio_event *gp_ev; ++ struct fsm_state *state; ++ int i; ++ ++ dev_dbg(gf->dev, "go_to_state_deferred(%s)\n", ++ new_state ? new_state->name : ""); ++ + spin_lock(&gf->spinlock); + + if (gf->next_state) { +@@ -335,57 +360,31 @@ static void gpio_fsm_go_to_state(struct + + gf->next_state = new_state; + state = gf->current_state; +- gf->delay_target_state = NULL; + +- if (state) { +- /* Disarm any GPIO IRQs */ +- for (i = 0; i < state->num_gpio_events; i++) { +- gp_ev = &state->gpio_events[i]; +- inp_state = &gf->input_gpio_states[gp_ev->index]; +- inp_state->target = NULL; +- } ++ /* Disarm any GPIO IRQs */ ++ for (i = 0; i < state->num_gpio_events; i++) { ++ gp_ev = &state->gpio_events[i]; ++ inp_state = &gf->input_gpio_states[gp_ev->index]; ++ inp_state->target = NULL; + } + + spin_unlock(&gf->spinlock); + +- if (new_state) +- schedule_work(&gf->work); ++ schedule_work(&gf->work); + } + + static void gpio_fsm_work(struct work_struct *work) + { +- struct input_gpio_state *inp_state; + struct fsm_state *new_state; +- struct fsm_state *state; +- struct gpio_event *gp_ev; + struct gpio_fsm *gf; +- int i; + + gf = container_of(work, struct gpio_fsm, work); + spin_lock(&gf->spinlock); +- state = gf->current_state; + new_state = gf->next_state; +- if (!new_state) +- new_state = gf->delay_target_state; + gf->next_state = NULL; +- gf->delay_target_state = NULL; + spin_unlock(&gf->spinlock); + +- if (state) { +- /* Disable any enabled GPIO IRQs */ +- for (i = 0; i < state->num_gpio_events; i++) { +- gp_ev = &state->gpio_events[i]; +- inp_state = &gf->input_gpio_states[gp_ev->index]; +- if (inp_state->enabled) { +- inp_state->enabled = false; +- irq_set_irq_type(inp_state->irq, +- IRQF_TRIGGER_NONE); +- } +- } +- } +- +- if (new_state) +- gpio_fsm_enter_state(gf, new_state); ++ gpio_fsm_go_to_state(gf, new_state); + } + + static irqreturn_t gpio_fsm_gpio_irq_handler(int irq, void *dev_id) +@@ -404,7 +403,7 @@ static irqreturn_t gpio_fsm_gpio_irq_han + if (gf->debug) + dev_info(gf->dev, "GF_IN %d->%d -> %s\n", + inp_state->index, inp_state->value, target->name); +- gpio_fsm_go_to_state(gf, target); ++ gpio_fsm_go_to_state_deferred(gf, target); + return IRQ_HANDLED; + } + +@@ -416,12 +415,11 @@ static void gpio_fsm_timer(struct timer_ + target = gf->delay_target_state; + if (!target) + return; +- + if (gf->debug) + dev_info(gf->dev, "GF_DELAY %d -> %s\n", gf->delay_ms, + target->name); + +- gpio_fsm_go_to_state(gf, target); ++ gpio_fsm_go_to_state_deferred(gf, target); + } + + int gpio_fsm_parse_signals(struct gpio_fsm *gf, struct fsm_state *state, +@@ -1119,7 +1117,7 @@ static int gpio_fsm_probe(struct platfor + if (gf->debug) + dev_info(gf->dev, "Start -> %s\n", gf->start_state->name); + +- gpio_fsm_go_to_state(gf, gf->start_state); ++ gpio_fsm_enter_state(gf, gf->start_state); + + return devm_gpiochip_add_data(dev, &gf->gc, gf); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch b/target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch new file mode 100644 index 0000000000..33150551b3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch @@ -0,0 +1,63 @@ +From bf9fb25f3265605572f04e5c7836bb83ee345236 Mon Sep 17 00:00:00 2001 +From: Chao Yu +Date: Fri, 30 Dec 2022 23:43:32 +0800 +Subject: [PATCH] f2fs: fix to avoid NULL pointer dereference in + f2fs_issue_flush() + +commit b3d83066cbebc76dbac8a5fca931f64b4c6fff34 upstream. + +With below two cases, it will cause NULL pointer dereference when +accessing SM_I(sbi)->fcc_info in f2fs_issue_flush(). + +a) If kthread_run() fails in f2fs_create_flush_cmd_control(), it will +release SM_I(sbi)->fcc_info, + +- mount -o noflush_merge /dev/vda /mnt/f2fs +- mount -o remount,flush_merge /dev/vda /mnt/f2fs -- kthread_run() fails +- dd if=/dev/zero of=/mnt/f2fs/file bs=4k count=1 conv=fsync + +b) we will never allocate memory for SM_I(sbi)->fcc_info w/ below +testcase, + +- mount -o ro /dev/vda /mnt/f2fs +- mount -o rw,remount /dev/vda /mnt/f2fs +- dd if=/dev/zero of=/mnt/f2fs/file bs=4k count=1 conv=fsync + +In order to fix this issue, let change as below: +- fix error path handling in f2fs_create_flush_cmd_control(). +- allocate SM_I(sbi)->fcc_info even if readonly is on. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +--- + fs/f2fs/segment.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -663,9 +663,7 @@ init_thread: + "f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev)); + if (IS_ERR(fcc->f2fs_issue_flush)) { + err = PTR_ERR(fcc->f2fs_issue_flush); +- kfree(fcc); +- SM_I(sbi)->fcc_info = NULL; +- return err; ++ fcc->f2fs_issue_flush = NULL; + } + + return err; +@@ -5062,11 +5060,9 @@ int f2fs_build_segment_manager(struct f2 + + init_f2fs_rwsem(&sm_info->curseg_lock); + +- if (!f2fs_readonly(sbi->sb)) { +- err = f2fs_create_flush_cmd_control(sbi); +- if (err) +- return err; +- } ++ err = f2fs_create_flush_cmd_control(sbi); ++ if (err) ++ return err; + + err = create_discard_cmd_control(sbi); + if (err) diff --git a/target/linux/bcm27xx/patches-6.1/950-0177-hwrng-iproc-rng200-Add-BCM2838-support.patch b/target/linux/bcm27xx/patches-6.1/950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch similarity index 88% rename from target/linux/bcm27xx/patches-6.1/950-0177-hwrng-iproc-rng200-Add-BCM2838-support.patch rename to target/linux/bcm27xx/patches-6.1/950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch index 9a36dd1bcd..a179d930df 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0177-hwrng-iproc-rng200-Add-BCM2838-support.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch @@ -1,4 +1,4 @@ -From b642f64d629df5515f3a01fc5b2e17c3fa7b404c Mon Sep 17 00:00:00 2001 +From e079555a4c68356e58249cfc041b28f6eb455bd5 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 4 May 2019 17:06:15 +0200 Subject: [PATCH] hwrng: iproc-rng200: Add BCM2838 support @@ -17,8 +17,8 @@ Fixes: "hwrng: iproc-rng200: Add BCM2838 support" Signed-off-by: Phil Elwell --- drivers/char/hw_random/Kconfig | 2 +- - drivers/char/hw_random/iproc-rng200.c | 78 +++++++++++++++++++++++++-- - 2 files changed, 76 insertions(+), 4 deletions(-) + drivers/char/hw_random/iproc-rng200.c | 79 ++++++++++++++++++++++++++- + 2 files changed, 77 insertions(+), 4 deletions(-) --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -33,7 +33,15 @@ Signed-off-by: Phil Elwell module will be called iproc-rng200 --- a/drivers/char/hw_random/iproc-rng200.c +++ b/drivers/char/hw_random/iproc-rng200.c -@@ -21,6 +21,7 @@ +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -21,6 +22,7 @@ #define RNG_CTRL_OFFSET 0x00 #define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF #define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001 @@ -41,7 +49,7 @@ Signed-off-by: Phil Elwell #define RNG_SOFT_RESET_OFFSET 0x04 #define RNG_SOFT_RESET 0x00000001 -@@ -28,16 +29,23 @@ +@@ -28,16 +30,23 @@ #define RBG_SOFT_RESET_OFFSET 0x08 #define RBG_SOFT_RESET 0x00000001 @@ -65,7 +73,7 @@ Signed-off-by: Phil Elwell struct iproc_rng200_dev { struct hwrng rng; -@@ -158,6 +166,64 @@ static int iproc_rng200_init(struct hwrn +@@ -158,6 +167,64 @@ static int iproc_rng200_init(struct hwrn return 0; } @@ -130,7 +138,7 @@ Signed-off-by: Phil Elwell static void iproc_rng200_cleanup(struct hwrng *rng) { struct iproc_rng200_dev *priv = to_rng_priv(rng); -@@ -184,11 +250,17 @@ static int iproc_rng200_probe(struct pla +@@ -184,11 +251,17 @@ static int iproc_rng200_probe(struct pla dev_set_drvdata(dev, priv); diff --git a/target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch b/target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch new file mode 100644 index 0000000000..b08676253e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch @@ -0,0 +1,39 @@ +From 6f634d7efb8876e5953c30c0a613aaa5f575fe05 Mon Sep 17 00:00:00 2001 +From: Jim Quinlan +Date: Tue, 11 Oct 2022 14:42:07 -0400 +Subject: [PATCH] PCI: brcmstb: Wait for 100ms following PERST# deassert + +commit 3ae140ad827b359bc4fa7c7985691c4c1e3ca8f4 upstream. + +Be prudent and give some time for power and clocks to become stable. As +described in the PCIe CEM specification sections 2.2 and 2.2.1; as well as +PCIe r5.0, 6.6.1. + +Link: https://lore.kernel.org/r/20221011184211.18128-3-jim2101024@gmail.com +Signed-off-by: Jim Quinlan +Signed-off-by: Lorenzo Pieralisi +Acked-by: Florian Fainelli +--- + drivers/pci/controller/pcie-brcmstb.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1038,8 +1038,15 @@ static int brcm_pcie_start_link(struct b + pcie->perst_set(pcie, 0); + + /* +- * Give the RC/EP time to wake up, before trying to configure RC. +- * Intermittently check status for link-up, up to a total of 100ms. ++ * Wait for 100ms after PERST# deassertion; see PCIe CEM specification ++ * sections 2.2, PCIe r5.0, 6.6.1. ++ */ ++ msleep(100); ++ ++ /* ++ * Give the RC/EP even more time to wake up, before trying to ++ * configure RC. Intermittently check status for link-up, up to a ++ * total of 100ms. + */ + for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5) + msleep(5); diff --git a/target/linux/bcm27xx/patches-6.1/950-0850-overlays-Add-a-sample-hat_map.patch b/target/linux/bcm27xx/patches-6.1/950-0850-overlays-Add-a-sample-hat_map.patch new file mode 100644 index 0000000000..19550b6fd5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0850-overlays-Add-a-sample-hat_map.patch @@ -0,0 +1,47 @@ +From cc08810f89e52337a99cc6ae5f53f08588357c5f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Sep 2023 20:31:34 +0100 +Subject: [PATCH] overlays: Add a sample hat_map + +The HAT map is way of associating named overlays with HATs whose +EEPROMs were programmed with the contents of the overlay. +Unfortunately, change in the DT and kernel drivers has meant that some +of these embedded overlays no longer function, or even don't apply. + +The HAT map is a mapping from HAT UUIDs to overlay names. If a HAT with +a listed UUID is detected, the embedded overlay is ignored and the +overlay named in the mapping is loaded in its place. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/Makefile | 2 +- + arch/arm/boot/dts/overlays/hat_map.dts | 13 +++++++++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/overlays/hat_map.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -1,6 +1,6 @@ + # Overlays for the Raspberry Pi platform + +-dtb-$(CONFIG_ARCH_BCM2835) += overlay_map.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += overlay_map.dtb hat_map.dtb + + dtbo-$(CONFIG_ARCH_BCM2835) += \ + act-led.dtbo \ +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hat_map.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++ ++/ { ++ iqaudio-pi-codecplus { ++ uuid = [ dc1c9594 c1ab 4c6c acda a88dc59a3c5b ]; ++ overlay = "iqaudio-codec"; ++ }; ++ ++ recalbox-rgbdual { ++ uuid = [ 1c955808 681f 4bbc a2ef b7ea47cd388e ]; ++ overlay = "recalboxrgbdual"; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch b/target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch new file mode 100644 index 0000000000..aaf49e6a7c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch @@ -0,0 +1,26 @@ +From 406e7dc82be6ce1b81c88b418640daeef6c2be42 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Mon, 23 May 2022 16:56:44 +0100 +Subject: [PATCH] Revert "usb: phy: generic: Get the vbus supply" + +This reverts commit c0ea202fbc855d60bc4a0603ca52a9e80654b327. +--- + drivers/usb/phy/phy-generic.c | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/drivers/usb/phy/phy-generic.c ++++ b/drivers/usb/phy/phy-generic.c +@@ -265,13 +265,6 @@ int usb_phy_gen_create_phy(struct device + return -EPROBE_DEFER; + } + +- nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus"); +- if (PTR_ERR(nop->vbus_draw) == -ENODEV) +- nop->vbus_draw = NULL; +- if (IS_ERR(nop->vbus_draw)) +- return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), +- "could not get vbus regulator\n"); +- + nop->dev = dev; + nop->phy.dev = nop->dev; + nop->phy.label = "nop-xceiv"; diff --git a/target/linux/bcm27xx/patches-6.1/950-0853-dts-2712-Update-for-device-tree.patch b/target/linux/bcm27xx/patches-6.1/950-0853-dts-2712-Update-for-device-tree.patch new file mode 100644 index 0000000000..6a5c40ef4e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0853-dts-2712-Update-for-device-tree.patch @@ -0,0 +1,7672 @@ +From 1196bf1a7736ff0ab79f5012fa84082e298031a7 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 19 Sep 2023 15:55:00 +0100 +Subject: [PATCH] dts: 2712: Update for device tree + +dtoverlays: Fix up edt5406 entries to match with vc4-kms-dsi-7inch + +vc4-kms-dsi-7inch expects the touch fragment to be named ts_i2c_frag, +but edt5406 didn't do this. + +Fixes: 736d601fb38c ("dts: 2712: Update for device tree") + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-b.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 1 + + arch/arm/boot/dts/bcm2708-rpi-zero.dts | 1 + + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 3 + + arch/arm/boot/dts/bcm2709-rpi-cm2.dts | 3 + + arch/arm/boot/dts/bcm270x-rpi.dtsi | 3 + + arch/arm/boot/dts/bcm2710-rpi-2-b.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts | 3 + + arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 3 + + arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 3 + + arch/arm/boot/dts/bcm2711-rpi-cm4s.dts | 3 + + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 824 +++++++++++ + arch/arm/boot/dts/bcm2712-rpi.dtsi | 281 ++++ + arch/arm/boot/dts/bcm2712.dtsi | 1287 +++++++++++++++++ + arch/arm/boot/dts/overlays/Makefile | 23 + + arch/arm/boot/dts/overlays/README | 360 ++++- + .../dts/overlays/adau1977-adc-overlay.dts | 4 +- + .../dts/overlays/adau7002-simple-overlay.dts | 4 +- + .../overlays/akkordion-iqdacplus-overlay.dts | 4 +- + .../allo-boss-dac-pcm512x-audio-overlay.dts | 10 +- + .../overlays/allo-boss2-dac-audio-overlay.dts | 2 +- + .../dts/overlays/allo-digione-overlay.dts | 4 +- + .../allo-katana-dac-audio-overlay.dts | 2 +- + .../allo-piano-dac-pcm512x-audio-overlay.dts | 4 +- + ...o-piano-dac-plus-pcm512x-audio-overlay.dts | 4 +- + .../boot/dts/overlays/applepi-dac-overlay.dts | 4 +- + .../dts/overlays/arducam-64mp-overlay.dts | 2 +- + .../overlays/arducam-pivariety-overlay.dts | 2 +- + .../overlays/audioinjector-addons-overlay.dts | 4 +- + .../audioinjector-bare-i2s-overlay.dts | 6 +- + ...dioinjector-isolated-soundcard-overlay.dts | 4 +- + .../overlays/audioinjector-ultra-overlay.dts | 6 +- + .../audioinjector-wm8731-audio-overlay.dts | 4 +- + .../dts/overlays/audiosense-pi-overlay.dts | 4 +- + .../boot/dts/overlays/chipdip-dac-overlay.dts | 4 +- + .../dts/overlays/cirrus-wm5102-overlay.dts | 4 +- + .../boot/dts/overlays/dacberry400-overlay.dts | 4 +- + .../dts/overlays/dionaudio-kiwi-overlay.dts | 4 +- + .../dts/overlays/dionaudio-loco-overlay.dts | 4 +- + .../overlays/dionaudio-loco-v2-overlay.dts | 4 +- + .../dts/overlays/disable-bt-pi5-overlay.dts | 17 + + .../dts/overlays/disable-wifi-pi5-overlay.dts | 13 + + arch/arm/boot/dts/overlays/draws-overlay.dts | 6 +- + .../boot/dts/overlays/edt-ft5406-overlay.dts | 22 +- + arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 2 +- + .../boot/dts/overlays/fe-pi-audio-overlay.dts | 4 +- + .../boot/dts/overlays/ghost-amp-overlay.dts | 4 +- + .../googlevoicehat-soundcard-overlay.dts | 4 +- + .../dts/overlays/hifiberry-amp-overlay.dts | 4 +- + .../dts/overlays/hifiberry-amp100-overlay.dts | 11 +- + .../dts/overlays/hifiberry-amp3-overlay.dts | 4 +- + .../dts/overlays/hifiberry-dac-overlay.dts | 4 +- + .../overlays/hifiberry-dacplus-overlay.dts | 11 +- + .../overlays/hifiberry-dacplusadc-overlay.dts | 10 +- + .../hifiberry-dacplusadcpro-overlay.dts | 10 +- + .../overlays/hifiberry-dacplusdsp-overlay.dts | 4 +- + .../overlays/hifiberry-dacplushd-overlay.dts | 4 +- + .../dts/overlays/hifiberry-digi-overlay.dts | 4 +- + .../overlays/hifiberry-digi-pro-overlay.dts | 4 +- + .../boot/dts/overlays/i-sabre-q2m-overlay.dts | 4 +- + .../boot/dts/overlays/i2c0-pi5-overlay.dts | 34 + + .../boot/dts/overlays/i2c1-pi5-overlay.dts | 34 + + .../boot/dts/overlays/i2c2-pi5-overlay.dts | 21 + + .../boot/dts/overlays/i2c3-pi5-overlay.dts | 22 + + .../arm/boot/dts/overlays/i2s-dac-overlay.dts | 4 +- + arch/arm/boot/dts/overlays/imx219-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/imx258-overlay.dts | 2 +- + .../boot/dts/overlays/imx290_327-overlay.dtsi | 2 +- + arch/arm/boot/dts/overlays/imx296-overlay.dts | 2 +- + .../boot/dts/overlays/imx477_378-overlay.dtsi | 2 +- + arch/arm/boot/dts/overlays/imx519-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/imx708-overlay.dts | 4 +- + .../dts/overlays/iqaudio-codec-overlay.dts | 4 +- + .../boot/dts/overlays/iqaudio-dac-overlay.dts | 4 +- + .../dts/overlays/iqaudio-dacplus-overlay.dts | 4 +- + .../iqaudio-digi-wm8804-audio-overlay.dts | 4 +- + .../arm/boot/dts/overlays/irs1125-overlay.dts | 2 +- + .../dts/overlays/justboom-both-overlay.dts | 4 +- + .../dts/overlays/justboom-dac-overlay.dts | 4 +- + .../dts/overlays/justboom-digi-overlay.dts | 4 +- + .../boot/dts/overlays/max98357a-overlay.dts | 6 +- + .../boot/dts/overlays/mbed-dac-overlay.dts | 6 +- + .../boot/dts/overlays/merus-amp-overlay.dts | 4 +- + .../dts/overlays/midi-uart0-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart1-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart2-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart3-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart4-pi5-overlay.dts | 35 + + arch/arm/boot/dts/overlays/ov2311-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/ov5647-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/ov7251-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/ov9281-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/overlay_map.dts | 226 +++ + arch/arm/boot/dts/overlays/pibell-overlay.dts | 6 +- + .../arm/boot/dts/overlays/pifi-40-overlay.dts | 4 +- + .../boot/dts/overlays/pifi-dac-hd-overlay.dts | 4 +- + .../dts/overlays/pifi-dac-zero-overlay.dts | 4 +- + .../dts/overlays/pifi-mini-210-overlay.dts | 4 +- + .../arm/boot/dts/overlays/pisound-overlay.dts | 4 +- + .../boot/dts/overlays/proto-codec-overlay.dts | 4 +- + .../rra-digidac1-wm8741-audio-overlay.dts | 4 +- + .../dts/overlays/spi2-1cs-pi5-overlay.dts | 33 + + .../dts/overlays/spi2-2cs-pi5-overlay.dts | 44 + + .../dts/overlays/spi3-1cs-pi5-overlay.dts | 33 + + .../dts/overlays/spi3-2cs-pi5-overlay.dts | 44 + + .../dts/overlays/spi5-1cs-pi5-overlay.dts | 33 + + .../dts/overlays/spi5-2cs-pi5-overlay.dts | 44 + + .../dts/overlays/superaudioboard-overlay.dts | 6 +- + .../dts/overlays/tc358743-audio-overlay.dts | 10 +- + .../boot/dts/overlays/tc358743-overlay.dts | 2 +- + .../boot/dts/overlays/uart0-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart1-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart2-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart3-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart4-pi5-overlay.dts | 17 + + arch/arm/boot/dts/overlays/udrc-overlay.dts | 6 +- + .../dts/overlays/ugreen-dabboard-overlay.dts | 10 +- + .../dts/overlays/vc4-fkms-v3d-overlay.dts | 6 + + .../dts/overlays/vc4-fkms-v3d-pi4-overlay.dts | 6 + + .../overlays/vc4-kms-dsi-7inch-overlay.dts | 18 +- + .../vc4-kms-dsi-waveshare-panel-overlay.dts | 8 +- + .../dts/overlays/vc4-kms-v3d-pi5-overlay.dts | 147 ++ + .../dts/overlays/vc4-kms-vga666-overlay.dts | 9 +- + .../dts/overlays/wm8960-soundcard-overlay.dts | 4 +- + arch/arm/boot/dts/rp1.dtsi | 1168 +++++++++++++++ + arch/arm64/boot/dts/broadcom/Makefile | 1 + + .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 1 + + 134 files changed, 5143 insertions(+), 264 deletions(-) + create mode 100644 arch/arm/boot/dts/bcm2712-rpi-5-b.dts + create mode 100644 arch/arm/boot/dts/bcm2712-rpi.dtsi + create mode 100644 arch/arm/boot/dts/bcm2712.dtsi + create mode 100644 arch/arm/boot/dts/overlays/disable-bt-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/disable-wifi-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c0-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c1-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c2-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c3-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart0-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart1-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart2-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart3-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart4-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi2-1cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi2-2cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi3-1cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi3-2cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi5-1cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi5-2cs-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-v3d-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/rp1.dtsi + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -18,7 +18,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2709-rpi-cm2.dtb \ + bcm2710-rpi-cm3.dtb \ + bcm2711-rpi-cm4.dtb \ +- bcm2711-rpi-cm4s.dtb ++ bcm2711-rpi-cm4s.dtb \ ++ bcm2712-rpi-5-b.dtb + + dtb-$(CONFIG_ARCH_ALPINE) += \ + alpine-db.dtb +--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -192,6 +192,9 @@ i2c_arm: &i2c1 { + i2c_vc: &i2c0 { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts +@@ -203,6 +203,9 @@ i2c_arm: &i2c0 { + i2c_vc: &i2c1 { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -185,6 +185,9 @@ i2c_arm: &i2c1 { + i2c_vc: &i2c0 { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +@@ -19,6 +19,9 @@ cam0_reg: &cam0_regulator { + gpio = <&gpio 31 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + &uart0 { + status = "okay"; + }; +--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts +@@ -243,6 +243,7 @@ cam0_reg: &cam_dummy_reg { + + i2c_arm: &i2c1 {}; + i2c_vc: &i2c0 {}; ++i2c_csi_dsi0: &i2c0 {}; + + / { + __overrides__ { +--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts +@@ -178,6 +178,7 @@ cam0_reg: &cam_dummy_reg { + + i2c_arm: &i2c1 {}; + i2c_vc: &i2c0 {}; ++i2c_csi_dsi0: &i2c0 {}; + + / { + __overrides__ { +--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -186,6 +186,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2709-rpi-cm2.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-cm2.dts +@@ -20,6 +20,9 @@ cam0_reg: &cam0_regulator { + gpio = <&gpio 30 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + &uart0 { + status = "okay"; + }; +--- a/arch/arm/boot/dts/bcm270x-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm270x-rpi.dtsi +@@ -127,6 +127,9 @@ + status = "disabled"; + }; + ++i2s_clk_producer: &i2s {}; ++i2s_clk_consumer: &i2s {}; ++ + &clocks { + firmware = <&firmware>; + }; +--- a/arch/arm/boot/dts/bcm2710-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-2-b.dts +@@ -186,6 +186,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts +@@ -274,6 +274,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts +@@ -283,6 +283,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts +@@ -19,6 +19,9 @@ cam0_reg: &cam0_regulator { + gpio = <&gpio 31 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + &uart0 { + status = "okay"; + }; +--- a/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts +@@ -262,6 +262,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +@@ -400,6 +400,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts +@@ -409,6 +409,9 @@ cam0_reg: &cam1_reg { + gpio = <&expgpio 5 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2711-rpi-cm4s.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4s.dts +@@ -282,6 +282,9 @@ cam0_reg: &cam0_regulator { + status = "disabled"; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_hdmi=0'}"; +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -0,0 +1,824 @@ ++// 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 uart3 _uart3 ++#define uart4 _uart4 ++#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 Model B"; ++ ++ /* Will be filled by the bootloader */ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0 0 0x28000000>; ++ }; ++ ++ leds: leds { ++ compatible = "gpio-leds"; ++ ++ pwr_led: led-pwr { ++ label = "PWR"; ++ gpios = <&rp1_gpio 44 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "none"; ++ }; ++ ++ act_led: 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 ++ }; ++}; ++ ++rp1_target: &pcie2 { ++ 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; ++ }; ++}; ++ ++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" ++ ++// A few extra labels to keep overlays happy ++ ++i2c0if: &rp1_gpio {}; ++i2c0mux: &rp1_gpio {}; ++ ++i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only ++ pinctrl-0 = <&rp1_i2c6_38_39>; ++ pinctrl-names = "default"; ++}; ++ ++i2c_csi_dsi1: &i2c4 { // Note: This is for MIPI1 connector only ++ pinctrl-0 = <&rp1_i2c4_40_41>; ++ pinctrl-names = "default"; ++}; ++ ++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; ++ //broken-cd; ++ //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 { ++ function = "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 = "coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; ++ 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_SD", // GPIO0 ++ "ID_SC", // GPIO1 ++ "PIN3", // GPIO2 ++ "PIN5", // GPIO3 ++ "PIN7", // GPIO4 ++ "PIN29", // GPIO5 ++ "PIN31", // GPIO6 ++ "PIN26", // GPIO7 ++ "PIN24", // GPIO8 ++ "PIN21", // GPIO9 ++ "PIN19", // GPIO10 ++ "PIN23", // GPIO11 ++ "PIN32", // GPIO12 ++ "PIN33", // GPIO13 ++ "PIN8", // GPIO14 ++ "PIN10", // GPIO15 ++ "PIN36", // GPIO16 ++ "PIN11", // GPIO17 ++ "PIN12", // GPIO18 ++ "PIN35", // GPIO19 ++ "PIN38", // GPIO20 ++ "PIN40", // GPIO21 ++ "PIN15", // GPIO22 ++ "PIN16", // GPIO23 ++ "PIN18", // GPIO24 ++ "PIN22", // GPIO25 ++ "PIN37", // GPIO26 ++ "PIN13", // 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; ++ 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; ++ }; ++ ++ __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"; ++ nvme = <&pciex1>, "status"; ++ pciex1 = <&pciex1>, "status"; ++ pciex1_gen = <&pciex1> , "max-link-speed:0"; ++ pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; ++ random = <&random>, "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 = <&act_led>, "active-low?"; ++ act_led_trigger = <&act_led>, "linux,default-trigger"; ++ pwr_led_activelow = <&pwr_led>, "gpios:8"; ++ pwr_led_trigger = <&pwr_led>, "linux,default-trigger"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2712-rpi.dtsi +@@ -0,0 +1,281 @@ ++// 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>; ++ }; ++ ++ /* 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; ++ }; ++}; ++ ++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 { ++ /* ++ * RPi4'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"; ++ }; ++}; ++ ++&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"; ++ }; ++}; ++ ++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 { }; ++ ++i2c_vc: &i2c0 { // This is pins 27,28 on the header (not MIPI) ++ pinctrl-0 = <&rp1_i2c0_0_1>; ++ pinctrl-names = "default"; ++}; ++ ++i2c_arm: &i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2c1_2_3>; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2c2_4_5>; ++}; ++ ++&i2c3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2c3_6_7>; ++}; ++ ++&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/arm/boot/dts/bcm2712.dtsi +@@ -0,0 +1,1287 @@ ++// 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"; ++ /* SUN_L2 interrupt reg */ ++ reg = <0x7d503000 0x18>; ++ interrupt-parent = <&cpu_l2_irq>; ++ interrupts = <19>; ++ brcm,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"; ++ }; ++ ++ usb: usb@7c480000 { ++ compatible = "brcm,bcm2835-usb"; ++ reg = <0x7c480000 0x10000>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clocks = <&clk_usb>; ++ clock-names = "otg"; ++ phys = <&usbphy>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ ++ mop: mop@7c500000 { ++ compatible = "brcm,bcm2712-mop"; ++ reg = <0x7c500000 0x20>; ++ 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"; ++ }; ++ ++ uart3: serial@7d001600 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001600 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@7d001800 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001800 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 = <10000000>; ++ #pwm-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@7d00c800 { ++ compatible = "brcm,bcm2835-pwm"; ++ reg = <0x7d00c800 0x28>; ++ assigned-clock-rates = <10000000>; ++ #pwm-cells = <2>; ++ 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 = <200000>; ++ #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 = <200000>; ++ #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"; ++ }; ++ ++ uartc: serial@7d50e000 { ++ compatible = "brcm,bcm7271-uart"; ++ reg = <0x7d50e000 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 = <2>; ++ 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"; ++ }; ++ ++ sound: sound { ++ }; ++ }; ++ ++ 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 ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x000>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x100>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x200>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x300>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ l2_cache: l2-cache { ++ compatible = "cache"; ++ next-level-cache = <&l3_cache>; ++ }; ++ ++ l3_cache: l3-cache { ++ compatible = "cache"; ++ }; ++ }; ++ ++ 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>; ++ ++ brcm,enable-l1ss; ++ 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>; ++ ++ brcm,enable-mps-rcb; ++ brcm,enable-l1ss; ++ 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>; ++ }; ++ ++ genet: ethernet@1300000 { ++ compatible = "brcm,bcm2711-genet-v5"; ++ reg = <0x10 0x01300000 0x0 0x20010>; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ interrupts = , ++ ; ++ status = "disabled"; ++ phy-mode = "rgmii"; ++ fixed-link = <0x0 0x1 0x3e8 0x0 0x0>; ++ phy-speed = <0x3e8>; ++ phy-id = <0x101>; ++ phy-type = <0x6>; ++ local-mac-address = [ 00 10 18 d8 45 de ]; ++ device_type = "network"; ++ ++ genet_mdio: mdio@e14 { ++ compatible = "brcm,genet-mdio-v5"; ++ reg = <0xe14 0x8>; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ }; ++ }; ++ ++ syscon_piarbctl: syscon@400018 { ++ compatible = "brcm,syscon-piarbctl", "syscon", "simple-mfd"; ++ reg = <0x10 0x00400018 0x0 0x18>; ++ }; ++ ++ 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"; ++ 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>; ++ supports-cqe; ++ 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"; ++ }; ++ ++ sdio0: mmc@1108000 { ++ compatible = "brcm,bcm2711-emmc2"; ++ reg = <0x10 0x01108000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&clk_emmc2>; ++ 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 = <54000000>; ++ clock-output-names = "emmc2-clock"; ++ }; ++ }; ++ ++ usbphy: phy { ++ compatible = "usb-nop-xceiv"; ++ #phy-cells = <0>; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -49,8 +49,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + dionaudio-loco.dtbo \ + dionaudio-loco-v2.dtbo \ + disable-bt.dtbo \ ++ disable-bt-pi5.dtbo \ + disable-emmc2.dtbo \ + disable-wifi.dtbo \ ++ disable-wifi-pi5.dtbo \ + dpi18.dtbo \ + dpi18cpadhi.dtbo \ + dpi24.dtbo \ +@@ -106,8 +108,12 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + i2c-rtc-gpio.dtbo \ + i2c-sensor.dtbo \ + i2c0.dtbo \ ++ i2c0-pi5.dtbo \ + i2c1.dtbo \ ++ i2c1-pi5.dtbo \ ++ i2c2-pi5.dtbo \ + i2c3.dtbo \ ++ i2c3-pi5.dtbo \ + i2c4.dtbo \ + i2c5.dtbo \ + i2c6.dtbo \ +@@ -150,10 +156,15 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + media-center.dtbo \ + merus-amp.dtbo \ + midi-uart0.dtbo \ ++ midi-uart0-pi5.dtbo \ + midi-uart1.dtbo \ ++ midi-uart1-pi5.dtbo \ + midi-uart2.dtbo \ ++ midi-uart2-pi5.dtbo \ + midi-uart3.dtbo \ ++ midi-uart3-pi5.dtbo \ + midi-uart4.dtbo \ ++ midi-uart4-pi5.dtbo \ + midi-uart5.dtbo \ + minipitft13.dtbo \ + miniuart-bt.dtbo \ +@@ -231,14 +242,20 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + spi1-2cs.dtbo \ + spi1-3cs.dtbo \ + spi2-1cs.dtbo \ ++ spi2-1cs-pi5.dtbo \ + spi2-2cs.dtbo \ ++ spi2-2cs-pi5.dtbo \ + spi2-3cs.dtbo \ + spi3-1cs.dtbo \ ++ spi3-1cs-pi5.dtbo \ + spi3-2cs.dtbo \ ++ spi3-2cs-pi5.dtbo \ + spi4-1cs.dtbo \ + spi4-2cs.dtbo \ + spi5-1cs.dtbo \ ++ spi5-1cs-pi5.dtbo \ + spi5-2cs.dtbo \ ++ spi5-2cs-pi5.dtbo \ + spi6-1cs.dtbo \ + spi6-2cs.dtbo \ + ssd1306.dtbo \ +@@ -253,10 +270,15 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + tpm-slb9670.dtbo \ + tpm-slb9673.dtbo \ + uart0.dtbo \ ++ uart0-pi5.dtbo \ + uart1.dtbo \ ++ uart1-pi5.dtbo \ + uart2.dtbo \ ++ uart2-pi5.dtbo \ + uart3.dtbo \ ++ uart3-pi5.dtbo \ + uart4.dtbo \ ++ uart4-pi5.dtbo \ + uart5.dtbo \ + udrc.dtbo \ + ugreen-dabboard.dtbo \ +@@ -276,6 +298,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + vc4-kms-kippah-7inch.dtbo \ + vc4-kms-v3d.dtbo \ + vc4-kms-v3d-pi4.dtbo \ ++ vc4-kms-v3d-pi5.dtbo \ + vc4-kms-vga666.dtbo \ + vga666.dtbo \ + vl805.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -151,6 +151,9 @@ Params: + bdaddr=06:05:04:03:02:01 + will set the BDADDR to 01:02:03:04:05:06. + ++ 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. + +@@ -167,6 +170,9 @@ Params: + Default of GPIO expander 5 on CM4, but override + switches to normal GPIO. + ++ cooling_fan Enables the Pi 5 cooling fan (enabled ++ automatically by the firmware) ++ + eee Enable Energy Efficient Ethernet support for + compatible devices (default "on"). See also + "tx_lpi_timer". Pi3B+ only. +@@ -206,23 +212,29 @@ Params: + hdmi Set to "off" to disable the HDMI interface + (default "on") + ++ i2c An alias for i2c_arm ++ + i2c_arm Set to "on" to enable the ARM's i2c interface + (default "off") + ++ i2c_arm_baudrate Set the baudrate of the ARM's i2c interface ++ (default "100000") ++ ++ i2c_baudrate An alias for i2c_arm_baudrate ++ ++ i2c_csi_dsi Set to "on" to enable the i2c_csi_dsi interface ++ ++ i2c_csi_dsi0 Set to "on" to enable the i2c_csi_dsi0 interface ++ ++ i2c_csi_dsi1 Set to "on" to enable the i2c_csi_dsi1 interface ++ + i2c_vc Set to "on" to enable the i2c interface + usually reserved for the VideoCore processor + (default "off") + +- i2c An alias for i2c_arm +- +- i2c_arm_baudrate Set the baudrate of the ARM's i2c interface +- (default "100000") +- + i2c_vc_baudrate Set the baudrate of the VideoCore i2c interface + (default "100000") + +- i2c_baudrate An alias for i2c_arm_baudrate +- + i2s Set to "on" to enable the i2s interface + (default "off") + +@@ -237,11 +249,23 @@ Params: + krnbt_baudrate Set the baudrate of the PL011 UART when used + with krnbt=on + ++ nvme Alias for "pciex1" (2712 only) ++ + pcie Set to "off" to disable the PCIe interface + (default "on") + (2711 only, but not applicable on CM4S) + N.B. USB-A ports on 4B are subsequently disabled + ++ pciex1 Set to "on" to enable the external PCIe link ++ (2712 only, default "off") ++ ++ pciex1_gen Sets the PCIe "GEN"/speed for the external PCIe ++ link (2712 only, default "2") ++ ++ pciex1_no_l0s Set to "on" to disable ASPM L0s on the external ++ PCIe link for devices that have broken ++ implementations (2712 only, default "off") ++ + spi Set to "on" to enable the spi interfaces + (default "off") + +@@ -252,6 +276,11 @@ Params: + random Set to "on" to enable the hardware random + number generator (default "on") + ++ rtc_bbat_vchg Set the RTC backup battery charging voltage in ++ microvolts. If set to 0 or not specified, the ++ trickle charger is disabled. ++ (2712 only, default "0") ++ + sd Set to "off" to disable the SD card (or eMMC on + non-lite SKU of CM4). + (default "on") +@@ -276,18 +305,30 @@ Params: + sdio_overclock Clock (in MHz) to use when the MMC framework + requests 50MHz for the SDIO/WLAN interface. + ++ suspend Make the power button trigger a suspend rather ++ than a power-off (2712 only, default "off") ++ + tx_lpi_timer Set the delay in microseconds between going idle + and entering the low power state (default 600). + Requires EEE to be enabled - see "eee". + + uart0 Set to "off" to disable uart0 (default "on") + ++ uart0_console Move the kernel boot console to UART0 on pins ++ 6, 8 and 10 of the 40-way header (2712 only, ++ default "off") ++ + uart1 Set to "on" or "off" to enable or disable uart1 + (default varies) + + watchdog Set to "on" to enable the hardware watchdog + (default "off") + ++ wifiaddr Set an alternative WiFi MAC address. ++ The value should be a 6-byte hexadecimal value, ++ with or without colon separators, written in the ++ natural (big-endian) order. ++ + act_led_trigger Choose which activity the LED tracks. + Use "heartbeat" for a nice load indicator. + (default "mmc") +@@ -919,14 +960,16 @@ Params: 24db_digital_gain Allow ga + + + Name: disable-bt +-Info: Disable onboard Bluetooth on Pi 3B, 3B+, 3A+, 4B and Zero W, restoring +- UART0/ttyAMA0 over GPIOs 14 & 15. +- N.B. To disable the systemd service that initialises the modem so it +- doesn't use the UART, use 'sudo systemctl disable hciuart'. ++Info: Disable onboard Bluetooth on Bluetooth-capable Raspberry Pis. On Pis ++ prior to Pi 5 this restores UART0/ttyAMA0 over GPIOs 14 & 15. + Load: dtoverlay=disable-bt + Params: + + ++Name: disable-bt-pi5 ++Info: See disable-bt ++ ++ + Name: disable-emmc2 + Info: Disable EMMC2 controller on BCM2711. + The allows the onboard EMMC storage on Compute Module 4 to be disabled +@@ -936,11 +979,15 @@ Params: + + + Name: disable-wifi +-Info: Disable onboard WLAN on Pi 3B, 3B+, 3A+, 4B and Zero W. ++Info: Disable onboard WLAN on WiFi-capable Raspberry Pis. + Load: dtoverlay=disable-wifi + Params: + + ++Name: disable-wifi-pi5 ++Info: See disable-wifi ++ ++ + Name: dpi18 + Info: Overlay for a generic 18-bit DPI display + This uses GPIOs 0-21 (so no I2C, uart etc.), and activates the output +@@ -2233,6 +2280,15 @@ Info: Deprecated, legacy version of i2 + Load: + + ++Name: i2c0-pi5 ++Info: Enable i2c0 (Pi 5 only) ++Load: dtoverlay=i2c0-pi5,= ++Params: pins_0_1 Use GPIOs 0 and 1 (default) ++ pins_8_9 Use GPIOs 8 and 9 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ + Name: i2c1 + Info: Change i2c1 pin usage. Not all pin combinations are usable on all + platforms - platforms other then Compute Modules can only use this +@@ -2249,6 +2305,24 @@ Info: Deprecated, legacy version of i2 + Load: + + ++Name: i2c1-pi5 ++Info: Enable i2c1 (Pi 5 only) ++Load: dtoverlay=i2c1-pi5,= ++Params: pins_2_3 Use GPIOs 2 and 3 (default) ++ pins_10_11 Use GPIOs 10 and 11 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ ++Name: i2c2-pi5 ++Info: Enable i2c2 (Pi 5 only) ++Load: dtoverlay=i2c2-pi5,= ++Params: pins_4_5 Use GPIOs 4 and 5 (default) ++ pins_12_13 Use GPIOs 12 and 13 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ + Name: i2c3 + Info: Enable the i2c3 bus. BCM2711 only. + Load: dtoverlay=i2c3, +@@ -2258,6 +2332,16 @@ Params: pins_2_3 Use GPIO + "100000") + + ++Name: i2c3-pi5 ++Info: Enable i2c3 (Pi 5 only) ++Load: dtoverlay=i2c3-pi5,= ++Params: pins_6_7 Use GPIOs 6 and 7 (default) ++ pins_14_15 Use GPIOs 14 and 15 ++ pins_22_23 Use GPIOs 22 and 23 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ + Name: i2c4 + Info: Enable the i2c4 bus. BCM2711 only. + Load: dtoverlay=i2c4, +@@ -2869,6 +2953,10 @@ Load: dtoverlay=midi-uart0 + Params: + + ++Name: midi-uart0-pi5 ++Info: See midi-uart0 (this is the Pi 5 version) ++ ++ + Name: midi-uart1 + Info: Configures UART1 (ttyS0) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI +@@ -2876,29 +2964,45 @@ Load: dtoverlay=midi-uart1 + Params: + + ++Name: midi-uart1-pi5 ++Info: See midi-uart1 (this is the Pi 5 version) ++ ++ + Name: midi-uart2 +-Info: Configures UART2 (ttyAMA1) so that a requested 38.4kbaud actually gets ++Info: Configures UART2 (ttyAMA2) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart2 + Params: + + ++Name: midi-uart2-pi5 ++Info: See midi-uart2 (this is the Pi 5 version) ++ ++ + Name: midi-uart3 +-Info: Configures UART3 (ttyAMA2) so that a requested 38.4kbaud actually gets ++Info: Configures UART3 (ttyAMA3) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart3 + Params: + + ++Name: midi-uart3-pi5 ++Info: See midi-uart3 (this is the Pi 5 version) ++ ++ + Name: midi-uart4 +-Info: Configures UART4 (ttyAMA3) so that a requested 38.4kbaud actually gets ++Info: Configures UART4 (ttyAMA4) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart4 + Params: + + ++Name: midi-uart4-pi5 ++Info: See midi-uart4 (this is the Pi 5 version) ++ ++ + Name: midi-uart5 +-Info: Configures UART5 (ttyAMA4) so that a requested 38.4kbaud actually gets ++Info: Configures UART5 (ttyAMA5) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart5 + Params: +@@ -3921,105 +4025,131 @@ Name: spi1-1cs + Info: Enables spi1 with a single chip select (CS) line and associated spidev + dev node. The gpio pin number for the CS line and spidev device node + creation are configurable. +- N.B.: spi1 is only accessible on devices with a 40pin header, eg: +- A+, B+, Zero and PI2 B; as well as the Compute Module. ++ N.B.: spi1 is not accessible on old Pis without a 40-pin header. + Load: dtoverlay=spi1-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI1_CE0). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.0 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi1-2cs + Info: Enables spi1 with two chip select (CS) lines and associated spidev + dev nodes. The gpio pin numbers for the CS lines and spidev device node + creation are configurable. +- N.B.: spi1 is only accessible on devices with a 40pin header, eg: +- A+, B+, Zero and PI2 B; as well as the Compute Module. ++ N.B.: spi1 is not accessible on old Pis without a 40-pin header. + Load: dtoverlay=spi1-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI1_CE0). + cs1_pin GPIO pin for CS1 (default 17 - BCM SPI1_CE1). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.1 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi1-3cs + Info: Enables spi1 with three chip select (CS) lines and associated spidev + dev nodes. The gpio pin numbers for the CS lines and spidev device node + creation are configurable. +- N.B.: spi1 is only accessible on devices with a 40pin header, eg: +- A+, B+, Zero and PI2 B; as well as the Compute Module. ++ N.B.: spi1 is not accessible on old Pis without a 40-pin header. + Load: dtoverlay=spi1-3cs,= + Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI1_CE0). + cs1_pin GPIO pin for CS1 (default 17 - BCM SPI1_CE1). + cs2_pin GPIO pin for CS2 (default 16 - BCM SPI1_CE2). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.1 (default +- is 'okay' or enabled). +- cs2_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs2_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.2 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi2-1cs +-Info: Enables spi2 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin number for the CS line and spidev device node +- creation are configurable. +- N.B.: spi2 is only accessible with the Compute Module. ++Info: Enables spi2 on GPIOs 40-42 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. spi2-2cs-pi5 is ++ substituted on a Pi 5. ++ N.B.: spi2 is only accessible with the Compute Module or Pi 5. + Load: dtoverlay=spi2-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 43 - BCM SPI2_CE0). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.0 (default +- is 'okay' or enabled). ++ is 'on' or enabled). ++ ++ ++Name: spi2-1cs-pi5 ++Info: Enables spi2 on GPIOs 1-3 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi2-1cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 0). ++ cs0_spidev Set to 'off' to stop the creation of a ++ userspace device node /dev/spidev2.0 (default ++ is 'on' or enabled). + + + Name: spi2-2cs +-Info: Enables spi2 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. +- N.B.: spi2 is only accessible with the Compute Module. ++Info: Enables spi2 on GPIOs 40-42 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. spi2-2cs-pi5 is ++ substituted on a Pi 5. ++ N.B.: spi2 is only accessible with the Compute Module or Pi 5. + Load: dtoverlay=spi2-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 43 - BCM SPI2_CE0). + cs1_pin GPIO pin for CS1 (default 44 - BCM SPI2_CE1). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a ++ userspace device node /dev/spidev2.0 (default ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a ++ userspace device node /dev/spidev2.1 (default ++ is 'on' or enabled). ++ ++ ++Name: spi2-2cs-pi5 ++Info: Enables spi2 on GPIOs 1-3 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi2-2cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 0). ++ cs1_pin GPIO pin for CS1 (default 24). ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.1 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi2-3cs +-Info: Enables spi2 with three chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. +- N.B.: spi2 is only accessible with the Compute Module. ++Info: Enables spi2 on GPIOs 40-42 with three chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. ++ N.B.: spi2 is only accessible with the Compute Module or Pi 5. + Load: dtoverlay=spi2-3cs,= + Params: cs0_pin GPIO pin for CS0 (default 43 - BCM SPI2_CE0). + cs1_pin GPIO pin for CS1 (default 44 - BCM SPI2_CE1). + cs2_pin GPIO pin for CS2 (default 45 - BCM SPI2_CE2). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.1 (default +- is 'okay' or enabled). +- cs2_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs2_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.2 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi3-1cs +-Info: Enables spi3 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin number for the CS line and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi3 on GPIOs 1-3 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. BCM2711 only, ++ spi3-1cs-pi5 is substituted on Pi 5. + Load: dtoverlay=spi3-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0). + cs0_spidev Set to 'off' to prevent the creation of a +@@ -4027,10 +4157,22 @@ Params: cs0_pin GPIO pin + is 'on' or enabled). + + ++Name: spi3-1cs-pi5 ++Info: Enables spi3 on GPIOs 5-7 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi3-1cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 4). ++ cs0_spidev Set to 'off' to prevent the creation of a ++ userspace device node /dev/spidev3.0 (default ++ is 'on' or enabled). ++ ++ + Name: spi3-2cs +-Info: Enables spi3 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi3 on GPIO2 1-3 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 only, ++ spi3-2cs-pi5 is substituted on Pi 5. + Load: dtoverlay=spi3-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0). + cs1_pin GPIO pin for CS1 (default 24 - BCM SPI3_CE1). +@@ -4042,10 +4184,25 @@ Params: cs0_pin GPIO pin + is 'on' or enabled). + + ++Name: spi3-2cs-pi5 ++Info: Enables spi3 on GPIOs 5-7 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi3-2cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 4). ++ cs1_pin GPIO pin for CS1 (default 25). ++ cs0_spidev Set to 'off' to prevent the creation of a ++ userspace device node /dev/spidev3.0 (default ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to prevent the creation of a ++ userspace device node /dev/spidev3.1 (default ++ is 'on' or enabled). ++ ++ + Name: spi4-1cs +-Info: Enables spi4 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin number for the CS line and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi4 on GPIOs 5-7 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. BCM2711 only. + Load: dtoverlay=spi4-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0). + cs0_spidev Set to 'off' to prevent the creation of a +@@ -4054,9 +4211,9 @@ Params: cs0_pin GPIO pin + + + Name: spi4-2cs +-Info: Enables spi4 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi4 on GPIOs 5-6 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 only. + Load: dtoverlay=spi4-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0). + cs1_pin GPIO pin for CS1 (default 25 - BCM SPI4_CE1). +@@ -4069,23 +4226,27 @@ Params: cs0_pin GPIO pin + + + Name: spi5-1cs +-Info: Enables spi5 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi5 on GPIOs 13-15 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 and Pi 5. + Load: dtoverlay=spi5-1cs,= +-Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0). ++Params: cs0_pin GPIO pin for CS0 (default 12). + cs0_spidev Set to 'off' to prevent the creation of a + userspace device node /dev/spidev5.0 (default + is 'on' or enabled). + + ++Name: spi5-1cs-pi5 ++Info: See spi5-1cs ++ ++ + Name: spi5-2cs +-Info: Enables spi5 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi5 on GPIOs 13-15 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 and Pi 5. + Load: dtoverlay=spi5-2cs,= +-Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0). +- cs1_pin GPIO pin for CS1 (default 26 - BCM SPI5_CE1). ++Params: cs0_pin GPIO pin for CS0 (default 12). ++ cs1_pin GPIO pin for CS1 (default 26). + cs0_spidev Set to 'off' to prevent the creation of a + userspace device node /dev/spidev5.0 (default + is 'on' or enabled). +@@ -4094,6 +4255,10 @@ Params: cs0_pin GPIO pin + is 'on' or enabled). + + ++Name: spi5-2cs-pi5 ++Info: See spi5-2cs ++ ++ + Name: spi6-1cs + Info: Enables spi6 with a single chip select (CS) line and associated spidev + dev node. The gpio pin number for the CS line and spidev device node +@@ -4296,6 +4461,12 @@ Params: txd0_pin GPIO pin + 7(Alt3) for 32&33, 6(Alt2) for 36&37 + + ++Name: uart0-pi5 ++Info: Enable uart 0 on GPIOs 14-15. Pi 5 only. ++Load: dtoverlay=uart0-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 16-17 (default off) ++ ++ + Name: uart1 + Info: Change the pin usage of uart1 + Load: dtoverlay=uart1,= +@@ -4304,24 +4475,48 @@ Params: txd1_pin GPIO pin + rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15) + + ++Name: uart1-pi5 ++Info: Enable uart 1 on GPIOs 0-1. Pi 5 only. ++Load: dtoverlay=uart1-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 2-3 (default off) ++ ++ + Name: uart2 + Info: Enable uart 2 on GPIOs 0-3. BCM2711 only. + Load: dtoverlay=uart2, + Params: ctsrts Enable CTS/RTS on GPIOs 2-3 (default off) + + ++Name: uart2-pi5 ++Info: Enable uart 2 on GPIOs 4-5. Pi 5 only. ++Load: dtoverlay=uart2-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 6-7 (default off) ++ ++ + Name: uart3 + Info: Enable uart 3 on GPIOs 4-7. BCM2711 only. + Load: dtoverlay=uart3, + Params: ctsrts Enable CTS/RTS on GPIOs 6-7 (default off) + + ++Name: uart3-pi5 ++Info: Enable uart 3 on GPIOs 8-9. Pi 5 only. ++Load: dtoverlay=uart3-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 10-11 (default off) ++ ++ + Name: uart4 + Info: Enable uart 4 on GPIOs 8-11. BCM2711 only. + Load: dtoverlay=uart4, + Params: ctsrts Enable CTS/RTS on GPIOs 10-11 (default off) + + ++Name: uart4-pi5 ++Info: Enable uart 4 on GPIOs 12-13. Pi 5 only. ++Load: dtoverlay=uart4-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 14-15 (default off) ++ ++ + Name: uart5 + Info: Enable uart 5 on GPIOs 12-15. BCM2711 only. + Load: dtoverlay=uart5, +@@ -4530,6 +4725,8 @@ Params: sizex Touchscr + invy Touchscreen inverted y axis + swapxy Touchscreen swapped x y axis + disable_touch Disables the touch screen overlay driver ++ dsi0 Use DSI0 and i2c_csi_dsi0 (rather than ++ the default DSI1 and i2c_csi_dsi). + + + Name: vc4-kms-dsi-lt070me05000 +@@ -4579,6 +4776,8 @@ Params: 2_8_inch 2.8" 480 + invx Touchscreen inverted x axis + invy Touchscreen inverted y axis + swapxy Touchscreen swapped x y axis ++ dsi0 Use DSI0 and i2c_csi_dsi0 (rather than ++ the default DSI1 and i2c_csi_dsi). + + + Name: vc4-kms-kippah-7inch +@@ -4633,6 +4832,9 @@ Params: cma-512 CMA is 5 + nohdmi1 Disable HDMI 1 output + + ++Name: vc4-kms-v3d-pi5 ++Info: See vc4-kms-v3d-pi4 (this is the Pi 5 version) ++ + + Name: vc4-kms-vga666 + Info: Enable the VGA666 (resistor ladder ADC) for the vc4-kms-v3d driver. +--- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts +@@ -23,7 +23,7 @@ + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -33,7 +33,7 @@ + target = <&sound>; + __overlay__ { + compatible = "adi,adau1977-adc"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts ++++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts +@@ -5,7 +5,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -37,7 +37,7 @@ + "PDM_DAT", "Microphone Jack"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + dailink0_slave: simple-audio-card,codec { + sound-dai = <&adau7002_codec>; +--- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -38,7 +38,7 @@ + card_name = "Akkordion"; + dai_name = "IQaudIO DAC"; + dai_stream_name = "IQaudIO DAC HiFi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts +@@ -18,8 +18,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -46,7 +46,7 @@ + target = <&sound>; + boss_dac: __overlay__ { + compatible = "allo,boss-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + mute-gpios = <&gpio 6 1>; + status = "okay"; + }; +@@ -54,6 +54,8 @@ + + __overrides__ { + 24db_digital_gain = <&boss_dac>,"allo,24db_digital_gain?"; +- slave = <&boss_dac>,"allo,slave?"; ++ slave = <&boss_dac>,"allo,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&boss_dac>,"i2s-controller:0=",<&i2s_clk_producer>; + }; + }; +--- a/arch/arm/boot/dts/overlays/allo-boss2-dac-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-boss2-dac-audio-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/allo-digione-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-digione-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + __overlay__ { + compatible = "allo,allo-digione"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + clock44-gpio = <&gpio 5 0>; + clock48-gpio = <&gpio 6 0>; +--- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts +@@ -16,7 +16,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + target = <&sound>; + piano_dac: __overlay__ { + compatible = "allo,piano-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -41,7 +41,7 @@ + piano_dac: __overlay__ { + compatible = "allo,piano-dac-plus"; + audio-codec = <&allo_pcm5122_4c &allo_pcm5122_4d>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + mute1-gpios = <&gpio 6 1>; + mute2-gpios = <&gpio 25 1>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts +@@ -16,7 +16,7 @@ + format = "i2s"; + + p_cpu_dai: cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +@@ -40,7 +40,7 @@ + }; + + fragment@2 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/arducam-64mp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/arducam-64mp-overlay.dts +@@ -67,7 +67,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/arducam-pivariety-overlay.dts ++++ b/arch/arm/boot/dts/overlays/arducam-pivariety-overlay.dts +@@ -85,7 +85,7 @@ + rotation = <&arducam_pivariety>,"rotation:0"; + orientation = <&arducam_pivariety>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&arducam_pivariety>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -48,7 +48,7 @@ + mult-gpios = <&gpio 27 0>, <&gpio 22 0>, <&gpio 23 0>, + <&gpio 24 0>; + reset-gpios = <&gpio 5 0>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + codec = <&cs42448>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-bare-i2s-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-bare-i2s-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "audioinjector-bare"; +@@ -37,7 +37,7 @@ + simple-audio-card,frame-master = <&dailink0_master>; + + dailink0_master: simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-isolated-soundcard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-isolated-soundcard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -47,7 +47,7 @@ + snd: __overlay__ { + compatible = "ai,audioinjector-isolated-soundcard"; + mute-gpios = <&gpio 17 0>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + codec = <&cs4272>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -33,7 +33,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + + simple-audio-card,name = "audioinjector-ultra"; +@@ -57,7 +57,7 @@ + simple-audio-card,frame-master = <&sound_master>; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "ai,audioinjector-pi-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -75,7 +75,7 @@ + target = <&sound>; + __overlay__ { + compatible = "as,audiosense-pi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/chipdip-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/chipdip-dac-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "chipdip,chipdip-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + sr0-gpios = <&gpio 5 0>; + sr1-gpios = <&gpio 6 0>; + sr2-gpios = <&gpio 12 0>; +--- a/arch/arm/boot/dts/overlays/cirrus-wm5102-overlay.dts ++++ b/arch/arm/boot/dts/overlays/cirrus-wm5102-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -165,7 +165,7 @@ + target = <&sound>; + __overlay__ { + compatible = "wlf,rpi-cirrus"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dacberry400-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dacberry400-overlay.dts +@@ -5,7 +5,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -62,7 +62,7 @@ + target = <&sound>; + __overlay__ { + compatible = "osaelectronics,dacberry400"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dionaudio-kiwi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dionaudio-kiwi-overlay.dts +@@ -11,7 +11,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "dionaudio,dionaudio-kiwi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts +@@ -11,7 +11,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "dionaudio,loco-pcm5242-tpa3118"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts +@@ -15,13 +15,13 @@ + target = <&sound>; + frag0: __overlay__ { + compatible = "dionaudio,dionaudio-loco-v2"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/disable-bt-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/* Disable Bluetooth */ ++ ++#include ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&bluetooth>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/disable-wifi-pi5-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&sdio2>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/draws-overlay.dts ++++ b/arch/arm/boot/dts/overlays/draws-overlay.dts +@@ -9,7 +9,7 @@ + / { + compatible = "brcm,bcm2835"; + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -131,7 +131,7 @@ + target = <&sound>; + snd: __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "draws"; +@@ -153,7 +153,7 @@ + "Line Out", "LOL"; + + dailink0_master: simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + + simple-audio-card,codec { +--- a/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts ++++ b/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts +@@ -25,21 +25,21 @@ + }; + + __overrides__ { +- i2c0 = <&frag13>,"target:0=",<&i2c0>; +- i2c1 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c1", ++ i2c0 = <&ts_i2c_frag>,"target:0=",<&i2c0>; ++ i2c1 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c1", + <0>,"-0-1"; +- i2c3 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c3", ++ i2c3 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c3", + <0>,"-0-1"; +- i2c4 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c4", ++ i2c4 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c4", + <0>,"-0-1"; +- i2c5 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c5", ++ i2c5 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c5", + <0>,"-0-1"; +- i2c6 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c6", ++ i2c6 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c6", + <0>,"-0-1"; + addr = <&ft5406>,"reg:0"; + }; +--- a/arch/arm/boot/dts/overlays/edt-ft5406.dtsi ++++ b/arch/arm/boot/dts/overlays/edt-ft5406.dtsi +@@ -37,7 +37,7 @@ + }; + }; + +- frag13: fragment@13 { ++ ts_i2c_frag: fragment@13 { + target = <&i2c_csi_dsi>; + i2cbus: __overlay__ { + status = "okay"; +--- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts +@@ -53,7 +53,7 @@ + }; + + fragment@3 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -63,7 +63,7 @@ + target = <&sound>; + __overlay__ { + compatible = "fe-pi,fe-pi-audio"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/ghost-amp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ghost-amp-overlay.dts +@@ -14,7 +14,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -43,7 +43,7 @@ + target = <&sound>; + iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + mute-gpios = <& 0 0>; + iqaudio-dac,auto-mute-amp; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + target = <&sound>; + __overlay__ { + compatible = "googlevoicehat,googlevoicehat-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-amp"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-amp100-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp100-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -46,7 +46,7 @@ + target = <&sound>; + hifiberry_dacplus: __overlay__ { + compatible = "hifiberry,hifiberry-dacplus"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + mute-gpio = <&gpio 4 0>; + reset-gpio = <&gpio 17 0x11>; +@@ -56,7 +56,10 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplus>,"hifiberry,24db_digital_gain?"; +- slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?"; ++ slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplus>,"i2s-controller:0=",<&i2s_clk_producer>; ++ + leds_off = <&hifiberry_dacplus>,"hifiberry-dacplus,leds_off?"; + mute_ext_ctl = <&hifiberry_dacplus>,"hifiberry-dacplus,mute_ext_ctl:0"; + auto_mute = <&hifiberry_dacplus>,"hifiberry-dacplus,auto_mute?"; +--- a/arch/arm/boot/dts/overlays/hifiberry-amp3-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp3-overlay.dts +@@ -10,7 +10,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -50,7 +50,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-amp3"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -51,7 +51,7 @@ + target = <&sound>; + hifiberry_dacplus: __overlay__ { + compatible = "hifiberry,hifiberry-dacplus"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +@@ -59,7 +59,10 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplus>,"hifiberry,24db_digital_gain?"; +- slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?"; ++ slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplus>,"i2s-controller:0=",<&i2s_clk_producer>; ++ + leds_off = <&hifiberry_dacplus>,"hifiberry-dacplus,leds_off?"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -58,7 +58,7 @@ + target = <&sound>; + hifiberry_dacplusadc: __overlay__ { + compatible = "hifiberry,hifiberry-dacplusadc"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +@@ -66,7 +66,9 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplusadc>,"hifiberry,24db_digital_gain?"; +- slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?"; ++ slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplusadc>,"i2s-controller:0=",<&i2s_clk_producer>; + leds_off = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,leds_off?"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -56,7 +56,7 @@ + hifiberry_dacplusadcpro: __overlay__ { + compatible = "hifiberry,hifiberry-dacplusadcpro"; + audio-codec = <&hb_dac &hb_adc>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +@@ -64,7 +64,9 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,24db_digital_gain?"; +- slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?"; ++ slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplusadcpro>,"i2s-controller:0=",<&i2s_clk_producer>; + leds_off = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,leds_off?"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -84,7 +84,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-dacplushd"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + clocks = <&pll 0>; + reset-gpio = <&gpio 16 GPIO_ACTIVE_LOW>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + clock44-gpio = <&gpio 5 0>; + clock48-gpio = <&gpio 6 0>; +--- a/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts +@@ -9,13 +9,13 @@ + target = <&sound>; + frag0: __overlay__ { + compatible = "audiophonics,i-sabre-q2m"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c0-pi5-overlay.dts +@@ -0,0 +1,34 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c0>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&frag0>; ++ __overlay__ { ++ pinctrl-0 = <&rp1_i2c0_0_1>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&frag0>; ++ __dormant__ { ++ pinctrl-0 = <&rp1_i2c0_8_9>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_0_1 = <0>,"+1-2"; ++ pins_8_9 = <0>,"-1+2"; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c1-pi5-overlay.dts +@@ -0,0 +1,34 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c1>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&frag0>; ++ __overlay__ { ++ pinctrl-0 = <&rp1_i2c1_2_3>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&frag0>; ++ __dormant__ { ++ pinctrl-0 = <&rp1_i2c1_10_11>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_2_3 = <0>,"+1-2"; ++ pins_10_11 = <0>,"-1+2"; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c2-pi5-overlay.dts +@@ -0,0 +1,21 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c2>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ pinctrl-0 = <&rp1_i2c2_4_5>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_4_5 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c2_4_5>; ++ pins_12_13 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c2_12_13>; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c3-pi5-overlay.dts +@@ -0,0 +1,22 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c3>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ pinctrl-0 = <&rp1_i2c3_6_7>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_6_7 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c3_6_7>; ++ pins_14_15 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c3_14_15>; ++ pins_22_23 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c3_22_23>; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/i2s-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2s-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "rpi,rpi-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/imx219-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx219-overlay.dts +@@ -69,7 +69,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx258-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx258-overlay.dts +@@ -110,7 +110,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, +--- a/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi +@@ -95,7 +95,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx296-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx296-overlay.dts +@@ -94,7 +94,7 @@ + rotation = <&imx296>,"rotation:0"; + orientation = <&imx296>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&imx296>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi +@@ -65,7 +65,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, +--- a/arch/arm/boot/dts/overlays/imx519-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx519-overlay.dts +@@ -69,7 +69,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx708-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx708-overlay.dts +@@ -79,12 +79,12 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +- <&cam_node>, "VANA1-supply:0=",<&cam0_reg>, ++ <&cam_node>, "vana1-supply:0=",<&cam0_reg>, + <&vcm_node>, "VDD-supply:0=",<&cam0_reg>; + vcm = <&vcm_node>, "status", + <0>, "=4"; +--- a/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-codec"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + frag2: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + mute-gpios = <&gpio 22 0>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + wm8804_digi: __overlay__ { + compatible = "iqaudio,wm8804-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/irs1125-overlay.dts ++++ b/arch/arm/boot/dts/overlays/irs1125-overlay.dts +@@ -82,7 +82,7 @@ + + __overrides__ { + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&irs1125>, "clocks:0=",<&cam0_clk>; +--- a/arch/arm/boot/dts/overlays/justboom-both-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-both-overlay.dts +@@ -7,7 +7,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -54,7 +54,7 @@ + target = <&sound>; + frag3: __overlay__ { + compatible = "justboom,justboom-both"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + frag2: __overlay__ { + compatible = "justboom,justboom-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "justboom,justboom-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/max98357a-overlay.dts ++++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts +@@ -12,7 +12,7 @@ + + /* Enable I2S */ + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -52,7 +52,7 @@ + simple-audio-card,name = "MAX98357A"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + simple-audio-card,codec { + sound-dai = <&max98357a_dac>; +@@ -69,7 +69,7 @@ + simple-audio-card,name = "MAX98357A"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + simple-audio-card,codec { + sound-dai = <&max98357a_nsd>; +--- a/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "mbed-DAC"; +@@ -52,7 +52,7 @@ + simple-audio-card,format = "i2s"; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + + sound_master: simple-audio-card,codec { +--- a/arch/arm/boot/dts/overlays/merus-amp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/merus-amp-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -52,7 +52,7 @@ + target = <&sound>; + __overlay__ { + compatible = "merus,merus-amp"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart0-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart0_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart0>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart1-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk1 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart1_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart1>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart2-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk2 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart2_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart2>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart3-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk3 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart3_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart3>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart4-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk4 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart4_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart4>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/ov2311-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov2311-overlay.dts +@@ -60,7 +60,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts +@@ -72,7 +72,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <®_frag>, "target:0=",<&cam0_reg>, + <&clk_frag>, "target:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/ov7251-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov7251-overlay.dts +@@ -60,7 +60,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/ov9281-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov9281-overlay.dts +@@ -61,7 +61,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/overlay_map.dts ++++ b/arch/arm/boot/dts/overlays/overlay_map.dts +@@ -1,32 +1,100 @@ + /dts-v1/; + + / { ++ audremap { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ balena-fin { ++ bcm2835; ++ bcm2711; ++ }; ++ + bmp085_i2c-sensor { + deprecated = "use i2c-sensor,bmp085"; + }; + ++ cm-swap-i2c0 { ++ bcm2835; ++ bcm2711; ++ }; ++ + cutiepi-panel { + bcm2711; + }; + ++ disable-bt { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "disable-bt-pi5"; ++ }; ++ ++ disable-bt-pi5 { ++ bcm2712; ++ }; ++ + disable-emmc2 { + bcm2711; + }; + ++ disable-wifi { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "disable-wifi-pi5"; ++ }; ++ ++ disable-wifi-pi5 { ++ bcm2712; ++ }; ++ + highperi { + bcm2711; + }; + ++ i2c0 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "i2c0-pi5"; ++ }; ++ + i2c0-bcm2708 { + deprecated = "use i2c0"; + }; + ++ i2c0-pi5 { ++ bcm2712; ++ }; ++ ++ i2c1 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "i2c1-pi5"; ++ }; ++ + i2c1-bcm2708 { + deprecated = "use i2c1"; + }; + ++ i2c1-pi5 { ++ bcm2712; ++ }; ++ ++ i2c2 { ++ bcm2712 = "i2c2-pi5"; ++ }; ++ ++ i2c2-pi5 { ++ bcm2712; ++ }; ++ + i2c3 { + bcm2711; ++ bcm2712 = "i2c3-pi5"; ++ }; ++ ++ i2c3-pi5 { ++ bcm2712; + }; + + i2c4 { +@@ -41,26 +109,76 @@ + bcm2711; + }; + ++ i2s-gpio28-31 { ++ bcm2835; ++ bcm2711; ++ }; ++ + lirc-rpi { + deprecated = "use gpio-ir"; + }; + ++ midi-uart0 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "midi-uart0-pi5"; ++ }; ++ ++ midi-uart0-pi5 { ++ bcm2712; ++ }; ++ ++ midi-uart1 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "midi-uart1-pi5"; ++ }; ++ ++ midi-uart1-pi5 { ++ bcm2712; ++ }; ++ + midi-uart2 { + bcm2711; ++ bcm2712 = "midi-uart2-pi5"; ++ }; ++ ++ midi-uart2-pi5 { ++ bcm2712; + }; + + midi-uart3 { + bcm2711; ++ bcm2712 = "midi-uart3-pi5"; ++ }; ++ ++ midi-uart3-pi5 { ++ bcm2712; + }; + + midi-uart4 { + bcm2711; ++ bcm2712 = "midi-uart4-pi5"; ++ }; ++ ++ midi-uart4-pi5 { ++ bcm2712; + }; + + midi-uart5 { + bcm2711; + }; + ++ miniuart-bt { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ mmc { ++ bcm2835; ++ bcm2711; ++ }; ++ + mpu6050 { + deprecated = "use i2c-sensor,mpu6050"; + }; +@@ -118,6 +236,16 @@ + deprecated = "no longer necessary"; + }; + ++ sdhost { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ sdio { ++ bcm2835; ++ bcm2711; ++ }; ++ + sdio-1bit { + deprecated = "use sdio,bus_width=1,gpios_22_25"; + }; +@@ -126,6 +254,21 @@ + deprecated = "use 'dtparam=sd_poll_once' etc."; + }; + ++ smi { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ smi-dev { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ smi-nand { ++ bcm2835; ++ bcm2711; ++ }; ++ + spi0-cs { + renamed = "spi0-2cs"; + }; +@@ -134,12 +277,42 @@ + deprecated = "no longer necessary"; + }; + ++ spi2-1cs { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "spi2-1cs-pi5"; ++ }; ++ ++ spi2-1cs-pi5 { ++ bcm2712; ++ }; ++ ++ spi2-2cs { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "spi2-2cs-pi5"; ++ }; ++ ++ spi2-2cs-pi5 { ++ bcm2712; ++ }; ++ + spi3-1cs { + bcm2711; ++ bcm2712 = "spi3-1cs-pi5"; ++ }; ++ ++ spi3-1cs-pi5 { ++ bcm2712; + }; + + spi3-2cs { + bcm2711; ++ bcm2712 = "spi3-2cs-pi5"; ++ }; ++ ++ spi3-2cs-pi5 { ++ bcm2712; + }; + + spi4-1cs { +@@ -152,10 +325,20 @@ + + spi5-1cs { + bcm2711; ++ bcm2712 = "spi5-1cs-pi5"; ++ }; ++ ++ spi5-1cs-pi5 { ++ bcm2712; + }; + + spi5-2cs { + bcm2711; ++ bcm2712 = "spi5-2cs-pi5"; ++ }; ++ ++ spi5-2cs-pi5 { ++ bcm2712; + }; + + spi6-1cs { +@@ -166,16 +349,51 @@ + bcm2711; + }; + ++ uart0 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "uart0-pi5"; ++ }; ++ ++ uart0-pi5 { ++ bcm2712; ++ }; ++ ++ uart1 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "uart1-pi5"; ++ }; ++ ++ uart1-pi5 { ++ bcm2712; ++ }; ++ + uart2 { + bcm2711; ++ bcm2712 = "uart2-pi5"; ++ }; ++ ++ uart2-pi5 { ++ bcm2712; + }; + + uart3 { + bcm2711; ++ bcm2712 = "uart3-pi5"; ++ }; ++ ++ uart3-pi5 { ++ bcm2712; + }; + + uart4 { + bcm2711; ++ bcm2712 = "uart4-pi5"; ++ }; ++ ++ uart4-pi5 { ++ bcm2712; + }; + + uart5 { +@@ -198,10 +416,12 @@ + vc4-fkms-v3d { + bcm2835; + bcm2711 = "vc4-fkms-v3d-pi4"; ++ bcm2712 = "vc4-fkms-v3d-pi4"; + }; + + vc4-fkms-v3d-pi4 { + bcm2711; ++ bcm2712; + }; + + vc4-kms-dpi-at056tn53v1 { +@@ -211,10 +431,16 @@ + vc4-kms-v3d { + bcm2835; + bcm2711 = "vc4-kms-v3d-pi4"; ++ bcm2712 = "vc4-kms-v3d-pi5"; + }; + + vc4-kms-v3d-pi4 { + bcm2711; ++ bcm2712 = "vc4-kms-v3d-pi5"; ++ }; ++ ++ vc4-kms-v3d-pi5 { ++ bcm2712; + }; + + vl805 { +--- a/arch/arm/boot/dts/overlays/pibell-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pibell-overlay.dts +@@ -24,7 +24,7 @@ + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +@@ -43,7 +43,7 @@ + format = "i2s"; + + r_cpu_dai: cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + + /* example TDM slot configuration + dai-tdm-slot-num = <2>; +@@ -60,7 +60,7 @@ + format = "i2s"; + + p_cpu_dai: cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + + /* example TDM slot configuration + dai-tdm-slot-num = <2>; +--- a/arch/arm/boot/dts/overlays/pifi-40-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-40-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + pifi_40: __overlay__ { + compatible = "pifi,pifi-40"; + audio-codec = <&tas5711l &tas5711r>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + pdn-gpios = <&gpio 23 1>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/pifi-dac-hd-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-dac-hd-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -38,7 +38,7 @@ + simple-audio-card,dai-link@1 { + format = "i2s"; + cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + codec { + sound-dai = <&pcm5142>; +--- a/arch/arm/boot/dts/overlays/pifi-dac-zero-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-dac-zero-overlay.dts +@@ -16,7 +16,7 @@ + format = "i2s"; + + cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +@@ -40,7 +40,7 @@ + }; + + fragment@2 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/pifi-mini-210-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-mini-210-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "pifi,pifi-mini-210"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/pisound-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts +@@ -75,7 +75,7 @@ + target = <&sound>; + __overlay__ { + compatible = "blokaslabs,pisound"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + + pinctrl-names = "default"; +@@ -108,7 +108,7 @@ + }; + + fragment@7 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/proto-codec-overlay.dts ++++ b/arch/arm/boot/dts/overlays/proto-codec-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "rpi,rpi-proto"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + target = <&sound>; + __overlay__ { + compatible = "rra,digidac1-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi2-1cs-pi5-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi2>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 0 1>; ++ status = "okay"; ++ ++ spidev2_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs0_spidev = <&spidev2_0>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi2-2cs-pi5-overlay.dts +@@ -0,0 +1,44 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi2>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 0 1>, <&gpio 24 1>; ++ status = "okay"; ++ ++ spidev2_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ ++ spidev2_1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag1>,"cs-gpios:16"; ++ cs0_spidev = <&spidev2_0>,"status"; ++ cs1_spidev = <&spidev2_1>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi3-1cs-pi5-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi3>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 4 1>; ++ status = "okay"; ++ ++ spidev3_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs0_spidev = <&spidev3_0>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi3-2cs-pi5-overlay.dts +@@ -0,0 +1,44 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi3>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 4 1>, <&gpio 25 1>; ++ status = "okay"; ++ ++ spidev3_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ ++ spidev3_1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag1>,"cs-gpios:16"; ++ cs0_spidev = <&spidev3_0>,"status"; ++ cs1_spidev = <&spidev3_1>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi5-1cs-pi5-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi5>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 12 1>; ++ status = "okay"; ++ ++ spidev5_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs0_spidev = <&spidev5_0>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi5-2cs-pi5-overlay.dts +@@ -0,0 +1,44 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi5>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 12 1>, <&gpio 26 1>; ++ status = "okay"; ++ ++ spidev5_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ ++ spidev5_1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag1>,"cs-gpios:16"; ++ cs0_spidev = <&spidev5_0>,"status"; ++ cs1_spidev = <&spidev5_1>,"status"; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts +@@ -9,7 +9,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + + simple-audio-card,name = "SuperAudioBoard"; +@@ -32,7 +32,7 @@ + simple-audio-card,frame-master = <&sound_master>; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +@@ -45,7 +45,7 @@ + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -31,16 +31,16 @@ + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "tc358743"; +- simple-audio-card,bitclock-master = <&dailink0_slave>; +- simple-audio-card,frame-master = <&dailink0_slave>; ++ simple-audio-card,bitclock-master = <&dailink0_master>; ++ simple-audio-card,frame-master = <&dailink0_master>; + status = "okay"; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +- dailink0_slave: simple-audio-card,codec { ++ dailink0_master: simple-audio-card,codec { + sound-dai = <&tc358743_codec>; + }; + }; +--- a/arch/arm/boot/dts/overlays/tc358743-overlay.dts ++++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts +@@ -101,7 +101,7 @@ + 4lane = <0>, "-2+3-7+8"; + link-frequency = <&tc358743_0>,"link-frequencies#0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&tc358743>, "clocks:0=",<&cam0_clk>; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart0>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart0_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart1>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart1_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart2>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart2_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart3>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart3_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart4>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart4_ctsrts_pins>; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/udrc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts +@@ -9,7 +9,7 @@ + / { + compatible = "brcm,bcm2835"; + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + clocks = <&clocks BCM2835_CLOCK_PCM>; + clock-names = "pcm"; +@@ -71,7 +71,7 @@ + target = <&sound>; + snd: __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "udrc"; +@@ -93,7 +93,7 @@ + "Line Out", "LOL"; + + dailink0_master: simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + + simple-audio-card,codec { +--- a/arch/arm/boot/dts/overlays/ugreen-dabboard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ugreen-dabboard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -29,14 +29,14 @@ + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "dabboard"; +- simple-audio-card,bitclock-master = <&dailink0_slave>; +- simple-audio-card,frame-master = <&dailink0_slave>; ++ simple-audio-card,bitclock-master = <&dailink0_master>; ++ simple-audio-card,frame-master = <&dailink0_master>; + simple-audio-card,widgets = "Microphone", "Microphone Jack"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + }; +- dailink0_slave: simple-audio-card,codec { ++ dailink0_master: simple-audio-card,codec { + #sound-dai-cells = <0>; + sound-dai = <&dmic_codec>; + }; +--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts +@@ -37,4 +37,10 @@ + status = "okay"; + }; + }; ++ fragment@5 { ++ target-path = "/chosen"; ++ __overlay__ { ++ bootargs = "clk_ignore_unused"; ++ }; ++ }; + }; +--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts +@@ -41,4 +41,10 @@ + status = "okay"; + }; + }; ++ fragment@5 { ++ target-path = "/chosen"; ++ __overlay__ { ++ bootargs = "clk_ignore_unused"; ++ }; ++ }; + }; +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts +@@ -11,7 +11,7 @@ + / { + /* No compatible as it will have come from edt-ft5406.dtsi */ + +- fragment@0 { ++ dsi_frag: fragment@0 { + target = <&dsi1>; + __overlay__ { + #address-cells = <1>; +@@ -51,8 +51,8 @@ + fragment@1 { + target-path = "/"; + __overlay__ { +- panel_disp1: panel_disp1@0 { +- reg = <0>; ++ panel_disp: panel_disp@1 { ++ reg = <1>; + compatible = "raspberrypi,7inch-dsi", "simple-panel"; + backlight = <®_display>; + power-supply = <®_display>; +@@ -64,8 +64,8 @@ + }; + }; + +- reg_bridge: reg_bridge@0 { +- reg = <0>; ++ reg_bridge: reg_bridge@1 { ++ reg = <1>; + compatible = "regulator-fixed"; + regulator-name = "bridge_reg"; + gpio = <®_display 0 0>; +@@ -75,7 +75,7 @@ + }; + }; + +- fragment@2 { ++ i2c_frag: fragment@2 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -113,6 +113,12 @@ + }; + + __overrides__ { ++ dsi0 = <&dsi_frag>, "target:0=",<&dsi0>, ++ <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&ts_i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&panel_disp>, "reg:0=0", ++ <®_bridge>, "reg:0=0", ++ <®_bridge>, "regulator-name=bridge_reg_0"; + disable_touch = <0>, "-10-11-12"; + }; + }; +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts +@@ -9,7 +9,7 @@ + / { + compatible = "brcm,bcm2835"; + +- fragment@0 { ++ dsi_frag: fragment@0 { + target = <&dsi1>; + __overlay__ { + #address-cells = <1>; +@@ -29,7 +29,7 @@ + }; + }; + +- frag2: fragment@2 { ++ i2c_frag: fragment@2 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -112,12 +112,14 @@ + <&touch>, "touchscreen-size-y:0=1480", + <&touch>, "touchscreen-inverted-x?", + <&touch>, "touchscreen-swapped-x-y?"; +- i2c1 = <&frag2>, "target:0=",<&i2c1>, ++ i2c1 = <&i2c_frag>, "target:0=",<&i2c1>, + <0>, "-3-4+5"; + disable_touch = <&touch>, "status=disabled"; + rotation = <&panel>, "rotation:0"; + invx = <&touch>,"touchscreen-inverted-x?"; + invy = <&touch>,"touchscreen-inverted-y?"; + swapxy = <&touch>,"touchscreen-swapped-x-y?"; ++ dsi0 = <&dsi_frag>, "target:0=",<&dsi0>, ++ <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>; + }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi5-overlay.dts +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include "cma-overlay.dts" ++ ++&frag0 { ++ size = <((320-4)*1024*1024)>; ++}; ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@1 { ++ target = <&fb>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&aon_intr>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ddc0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&ddc1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&hdmi0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&hdmi1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&hvs>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&mop>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&moplet>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&pixelvalve0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@11 { ++ target = <&pixelvalve1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@12 { ++ target = <&v3d>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@13 { ++ target = <&vec>; ++ frag13: __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@14 { ++ target = <&hdmi0>; ++ __dormant__ { ++ dmas; ++ }; ++ }; ++ ++ fragment@15 { ++ target = <&hdmi1>; ++ __dormant__ { ++ dmas; ++ }; ++ }; ++ ++ fragment@16 { ++ target = <&disp_intr>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@17 { ++ target = <&vc4>; ++ __overlay__ { ++ /* IOMMU attaches here, where we allocate DMA buffers */ ++ iommus = <&iommu4>; ++ }; ++ }; ++ ++ __overrides__ { ++ audio = <0>,"!14"; ++ audio1 = <0>,"!15"; ++ noaudio = <0>,"=14", <0>,"=15"; ++ composite = <0>, "!3", ++ <0>, "!4", ++ <0>, "!5", ++ <0>, "!6", ++ <0>, "!10", ++ <0>, "!11", ++ <&frag13>, "status"; ++ nohdmi0 = <0>, "-3-5-10"; ++ nohdmi1 = <0>, "-4-6-11"; ++ nohdmi = <0>, "-3-4-5-6-10-11"; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/vc4-kms-vga666-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-vga666-overlay.dts +@@ -94,7 +94,14 @@ + }; + }; + ++ fragment@5 { ++ target = <&i2c_vc>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { +- ddc = <0>,"=2", <0>,"=3", <0>,"=4"; ++ ddc = <0>,"=2", <0>,"=3", <0>,"=4", <0>,"=5"; + }; + }; +--- a/arch/arm/boot/dts/overlays/wm8960-soundcard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/wm8960-soundcard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -65,7 +65,7 @@ + "RINPUT2", "Mic Jack"; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + dailink0_slave: simple-audio-card,codec { + sound-dai = <&wm8960>; +--- /dev/null ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -0,0 +1,1168 @@ ++#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 = <0>; ++ #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"; ++ }; ++ ++ // 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>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c1: i2c@74000 { ++ reg = <0xc0 0x40074000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c2: i2c@78000 { ++ reg = <0xc0 0x40078000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c3: i2c@7c000 { ++ reg = <0xc0 0x4007c000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c4: i2c@80000 { ++ reg = <0xc0 0x40080000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c5: i2c@84000 { ++ reg = <0xc0 0x40084000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c6: i2c@88000 { ++ reg = <0xc0 0x40088000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ 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 = <6144000>; ++ 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 = <6144000>; ++ 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>; ++ ++ 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"; ++ bias-pull-up; ++ }; ++ rp1_i2c6_38_39: rp1_i2c6_38_39 { ++ function = "i2c6"; ++ pins = "gpio38", "gpio39"; ++ bias-pull-up; ++ }; ++ rp1_i2c4_40_41: rp1_i2c4_40_41 { ++ function = "i2c4"; ++ pins = "gpio40", "gpio41"; ++ bias-pull-up; ++ }; ++ rp1_i2c5_44_45: rp1_i2c5_44_45 { ++ function = "i2c5"; ++ pins = "gpio44", "gpio45"; ++ bias-pull-up; ++ }; ++ rp1_i2c0_0_1: rp1_i2c0_0_1 { ++ function = "i2c0"; ++ pins = "gpio0", "gpio1"; ++ bias-pull-up; ++ }; ++ rp1_i2c0_8_9: rp1_i2c0_8_9 { ++ function = "i2c0"; ++ pins = "gpio8", "gpio9"; ++ bias-pull-up; ++ }; ++ rp1_i2c1_2_3: rp1_i2c1_2_3 { ++ function = "i2c1"; ++ pins = "gpio2", "gpio3"; ++ bias-pull-up; ++ }; ++ rp1_i2c1_10_11: rp1_i2c1_10_11 { ++ function = "i2c1"; ++ pins = "gpio10", "gpio11"; ++ bias-pull-up; ++ }; ++ rp1_i2c2_4_5: rp1_i2c2_4_5 { ++ function = "i2c2"; ++ pins = "gpio4", "gpio5"; ++ bias-pull-up; ++ }; ++ rp1_i2c2_12_13: rp1_i2c2_12_13 { ++ function = "i2c2"; ++ pins = "gpio12", "gpio13"; ++ bias-pull-up; ++ }; ++ rp1_i2c3_6_7: rp1_i2c3_6_7 { ++ function = "i2c3"; ++ pins = "gpio6", "gpio7"; ++ bias-pull-up; ++ }; ++ rp1_i2c3_14_15: rp1_i2c3_14_15 { ++ function = "i2c3"; ++ pins = "gpio14", "gpio15"; ++ bias-pull-up; ++ }; ++ rp1_i2c3_22_23: rp1_i2c3_22_23 { ++ function = "i2c3"; ++ pins = "gpio22", "gpio23"; ++ 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_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 = "snps,dwcmshc-sdhci"; ++ 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 = "snps,dwcmshc-sdhci"; ++ 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,tx-max-burst-prd = <8>; ++ snps,tx-thr-num-pkt-prd = <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,tx-max-burst-prd = <8>; ++ snps,tx-thr-num-pkt-prd = <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>, // 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"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI0_DPI>; ++ assigned-clock-rates = <25000000>; ++ assigned-clock-parents = <0>, <&clksrc_mipi0_dsi_byteclk>; ++ }; ++ ++ 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>, // 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"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI1_DPI>; ++ 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; */ ++ /* 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>; ++ }; ++ 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>; ++ }; ++}; ++ ++/ { ++ rp1_vdd_3v3: rp1_vdd_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd-3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++}; +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -16,6 +16,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rp + dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb + dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4.dtb + dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4s.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-5-b.dtb + + subdir-y += bcmbca + subdir-y += northstar2 +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +@@ -0,0 +1 @@ ++#include "../../../../arm/boot/dts/bcm2712-rpi-5-b.dts" diff --git a/target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch b/target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch new file mode 100644 index 0000000000..7e39ac8abf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch @@ -0,0 +1,282 @@ +From fa18902ee1e53ad391a455a01be3ab2ea1c5af5f Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Fri, 21 May 2021 12:33:38 +0100 +Subject: [PATCH] gpio_brcmstb: Allow to build for ARCH_BCM2835 + +gpio-brcmstb: Report the correct bank width + +gpio: brcmstb: Use bank address as gpiochip label + +If the path to the device node is used as gpiochip label then +gpio-brcmstb instances with multiple banks end up with duplicated +names. Instead, use a combination of the driver name with the physical +address of the bank, which is both unique and helpful for devmem +debugging. + +Signed-off-by: Phil Elwell + +gpio: mmio: Add DIRECT mode for shared access + +The generic MMIO GPIO library uses shadow registers for efficiency, +but this breaks attempts by raspi-gpio to change other GPIOs in the +same bank. Add a DIRECT mode that makes fewer assumptions about the +existing register contents, but note that genuinely simultaneous +accesses are likely to lose updates. + +Signed-off-by: Phil Elwell + +gpio: brcmstb: Don't always clear interrupt mask + +If the GPIO controller is not being used as an interrupt source +leave the interrupt mask register alone. On BCM2712 it might be used +to generate interrupts to the VPU firmware, and on other devices it +doesn't matter since no interrupts will be generated. + +Signed-off-by: Phil Elwell +--- + drivers/gpio/Kconfig | 2 +- + drivers/gpio/gpio-brcmstb.c | 14 ++-- + drivers/gpio/gpio-mmio.c | 124 ++++++++++++++++++++++++++++++++++-- + include/linux/gpio/driver.h | 1 + + 4 files changed, 131 insertions(+), 10 deletions(-) + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -203,7 +203,7 @@ config GPIO_BCM_VIRT + config GPIO_BRCMSTB + tristate "BRCMSTB GPIO support" + default y if (ARCH_BRCMSTB || BMIPS_GENERIC) +- depends on OF_GPIO && (ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST) ++ depends on OF_GPIO && (ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM2835 || COMPILE_TEST) + select GPIO_GENERIC + select IRQ_DOMAIN + help +--- a/drivers/gpio/gpio-brcmstb.c ++++ b/drivers/gpio/gpio-brcmstb.c +@@ -640,6 +640,8 @@ static int brcmstb_gpio_probe(struct pla + #if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN) + flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER; + #endif ++ if (of_property_read_bool(np, "brcm,gpio-direct")) ++ flags |= BGPIOF_REG_DIRECT; + + of_property_for_each_u32(np, "brcm,gpio-bank-widths", prop, p, + bank_width) { +@@ -689,7 +691,9 @@ static int brcmstb_gpio_probe(struct pla + } + + gc->owner = THIS_MODULE; +- gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np); ++ gc->label = devm_kasprintf(dev, GFP_KERNEL, "gpio-brcmstb@%zx", ++ (size_t)res->start + ++ GIO_BANK_OFF(bank->id, 0)); + if (!gc->label) { + err = -ENOMEM; + goto fail; +@@ -698,7 +702,7 @@ static int brcmstb_gpio_probe(struct pla + gc->of_gpio_n_cells = 2; + gc->of_xlate = brcmstb_gpio_of_xlate; + /* not all ngpio lines are valid, will use bank width later */ +- gc->ngpio = MAX_GPIO_PER_BANK; ++ gc->ngpio = bank_width; + gc->offset = bank->id * MAX_GPIO_PER_BANK; + if (priv->parent_irq > 0) + gc->to_irq = brcmstb_gpio_to_irq; +@@ -707,8 +711,10 @@ static int brcmstb_gpio_probe(struct pla + * Mask all interrupts by default, since wakeup interrupts may + * be retained from S5 cold boot + */ +- need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank); +- gc->write_reg(reg_base + GIO_MASK(bank->id), 0); ++ if (priv->parent_irq > 0) { ++ need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank); ++ gc->write_reg(reg_base + GIO_MASK(bank->id), 0); ++ } + + err = gpiochip_add_data(gc, bank); + if (err) { +--- a/drivers/gpio/gpio-mmio.c ++++ b/drivers/gpio/gpio-mmio.c +@@ -232,6 +232,25 @@ static void bgpio_set(struct gpio_chip * + raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + } + ++static void bgpio_set_direct(struct gpio_chip *gc, unsigned int gpio, int val) ++{ ++ unsigned long mask = bgpio_line2mask(gc, gpio); ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&gc->bgpio_lock, flags); ++ ++ gc->bgpio_data = gc->read_reg(gc->reg_dat); ++ ++ if (val) ++ gc->bgpio_data |= mask; ++ else ++ gc->bgpio_data &= ~mask; ++ ++ gc->write_reg(gc->reg_dat, gc->bgpio_data); ++ ++ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); ++} ++ + static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, + int val) + { +@@ -324,6 +343,27 @@ static void bgpio_set_multiple_with_clea + gc->write_reg(gc->reg_clr, clear_mask); + } + ++static void bgpio_set_multiple_direct(struct gpio_chip *gc, ++ unsigned long *mask, ++ unsigned long *bits) ++{ ++ unsigned long flags; ++ unsigned long set_mask, clear_mask; ++ ++ raw_spin_lock_irqsave(&gc->bgpio_lock, flags); ++ ++ bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); ++ ++ gc->bgpio_data = gc->read_reg(gc->reg_dat); ++ ++ gc->bgpio_data |= set_mask; ++ gc->bgpio_data &= ~clear_mask; ++ ++ gc->write_reg(gc->reg_dat, gc->bgpio_data); ++ ++ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); ++} ++ + static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) + { + return 0; +@@ -361,6 +401,29 @@ static int bgpio_dir_in(struct gpio_chip + return 0; + } + ++static int bgpio_dir_in_direct(struct gpio_chip *gc, unsigned int gpio) ++{ ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&gc->bgpio_lock, flags); ++ ++ if (gc->reg_dir_in) ++ gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); ++ if (gc->reg_dir_out) ++ gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); ++ ++ gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); ++ ++ if (gc->reg_dir_in) ++ gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); ++ if (gc->reg_dir_out) ++ gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); ++ ++ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); ++ ++ return 0; ++} ++ + static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) + { + /* Return 0 if output, 1 if input */ +@@ -399,6 +462,28 @@ static void bgpio_dir_out(struct gpio_ch + raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + } + ++static void bgpio_dir_out_direct(struct gpio_chip *gc, unsigned int gpio, ++ int val) ++{ ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&gc->bgpio_lock, flags); ++ ++ if (gc->reg_dir_in) ++ gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); ++ if (gc->reg_dir_out) ++ gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); ++ ++ gc->bgpio_dir |= bgpio_line2mask(gc, gpio); ++ ++ if (gc->reg_dir_in) ++ gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); ++ if (gc->reg_dir_out) ++ gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); ++ ++ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); ++} ++ + static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, + int val) + { +@@ -415,6 +500,22 @@ static int bgpio_dir_out_val_first(struc + return 0; + } + ++static int bgpio_dir_out_dir_first_direct(struct gpio_chip *gc, ++ unsigned int gpio, int val) ++{ ++ bgpio_dir_out_direct(gc, gpio, val); ++ gc->set(gc, gpio, val); ++ return 0; ++} ++ ++static int bgpio_dir_out_val_first_direct(struct gpio_chip *gc, ++ unsigned int gpio, int val) ++{ ++ gc->set(gc, gpio, val); ++ bgpio_dir_out_direct(gc, gpio, val); ++ return 0; ++} ++ + static int bgpio_setup_accessors(struct device *dev, + struct gpio_chip *gc, + bool byte_be) +@@ -508,6 +609,9 @@ static int bgpio_setup_io(struct gpio_ch + } else if (flags & BGPIOF_NO_OUTPUT) { + gc->set = bgpio_set_none; + gc->set_multiple = NULL; ++ } else if (flags & BGPIOF_REG_DIRECT) { ++ gc->set = bgpio_set_direct; ++ gc->set_multiple = bgpio_set_multiple_direct; + } else { + gc->set = bgpio_set; + gc->set_multiple = bgpio_set_multiple; +@@ -544,11 +648,21 @@ static int bgpio_setup_direction(struct + if (dirout || dirin) { + gc->reg_dir_out = dirout; + gc->reg_dir_in = dirin; +- if (flags & BGPIOF_NO_SET_ON_INPUT) +- gc->direction_output = bgpio_dir_out_dir_first; +- else +- gc->direction_output = bgpio_dir_out_val_first; +- gc->direction_input = bgpio_dir_in; ++ if (flags & BGPIOF_REG_DIRECT) { ++ if (flags & BGPIOF_NO_SET_ON_INPUT) ++ gc->direction_output = ++ bgpio_dir_out_dir_first_direct; ++ else ++ gc->direction_output = ++ bgpio_dir_out_val_first_direct; ++ gc->direction_input = bgpio_dir_in_direct; ++ } else { ++ if (flags & BGPIOF_NO_SET_ON_INPUT) ++ gc->direction_output = bgpio_dir_out_dir_first; ++ else ++ gc->direction_output = bgpio_dir_out_val_first; ++ gc->direction_input = bgpio_dir_in; ++ } + gc->get_direction = bgpio_get_dir; + } else { + if (flags & BGPIOF_NO_OUTPUT) +--- a/include/linux/gpio/driver.h ++++ b/include/linux/gpio/driver.h +@@ -690,6 +690,7 @@ int bgpio_init(struct gpio_chip *gc, str + #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ + #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ + #define BGPIOF_NO_SET_ON_INPUT BIT(6) ++#define BGPIOF_REG_DIRECT BIT(7) /* ignore shadow registers */ + + int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq); diff --git a/target/linux/bcm27xx/patches-6.1/950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch b/target/linux/bcm27xx/patches-6.1/950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch new file mode 100644 index 0000000000..7e0886d7e6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch @@ -0,0 +1,20 @@ +From 22ae3b2ee3293278e647877b269a5aebad3f077d Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 27 May 2021 11:46:30 +0100 +Subject: [PATCH] Allow RESET_BRCMSTB on ARCH_BCM2835 + +--- + drivers/reset/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/reset/Kconfig ++++ b/drivers/reset/Kconfig +@@ -51,7 +51,7 @@ config RESET_BERLIN + + config RESET_BRCMSTB + tristate "Broadcom STB reset controller" +- depends on ARCH_BRCMSTB || COMPILE_TEST ++ depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST + default ARCH_BRCMSTB + help + This enables the reset controller driver for Broadcom STB SoCs using diff --git a/target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch new file mode 100644 index 0000000000..429c3e2fd2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch @@ -0,0 +1,1324 @@ +From af7e60a33f0b5ce84bffb69ba084ba1edd180195 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 9 Jun 2021 15:48:28 +0100 +Subject: [PATCH] pinctrl: bcm2712 pinctrl/pinconf driver + +pinctrl: bcm2712: Reject invalid pulls + +Reject attempts to set pulls on aon-sgpios, and fix pull shift +values. + +pinctrl: bcm2712: Add 7712 support, fix 2712 count + +Signed-off-by: Phil Elwell + +pinctrl-bcm2712: add EMMC pins so pulls can be set + +These pins have pad controls but not mux controls. They look enough like +GPIOs to squeeze in at the end of the list though. + +pinctrl: bcm2712: correct BCM2712C0 AON_GPIO pad pull control offset + +Signed-off-by: Jonathan Bell + +pinctrl: bcm2712: on C0 the regular GPIO pad control register moves too + +Signed-off-by: Jonathan Bell + +pinctrl: bcm2712: Implement (partially) pinconf_get + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Convert to generic pinconf + +Remove the legacy brcm,* pin configuration support and replace it with +a proper generic pinconf interface, using named functions instead of +alt function numbers. This is nicer for users, less error-prone, and +immune to some of the C0->D0 changes. + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Remove vestigial pull parameter + +Now the legacy brcm, pinconf parameters are no longer supported, this +custom pin config parameter is not needed. + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Guard against bad func numbers + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: A better attempt at D0 support + +The BCM2712D0 sparse pinctrl maps play havoc with the old GPIO_REGS +macro, so make the bit positions explicit. And delete the unwanted +GPIO and pinmux declarations on D0. + +Note that a Pi 5 with D0 requires a separate DTS file with "bcm2712d0" +compatible strings. + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Delete base register constants + +BCM2712D0 deletes many GPIOs and their associated mux and pad bits, +so much so that the offsets to the start of the pad control registers +changes. Remove the constant offsets from the *GPIO_REGS macros, +compensating by adjusting the per-GPIO values. + +Signed-off-by: Phil Elwell +--- + drivers/pinctrl/bcm/Kconfig | 9 + + drivers/pinctrl/bcm/Makefile | 1 + + drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1216 +++++++++++++++++++++++++ + 3 files changed, 1226 insertions(+) + create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c + +--- a/drivers/pinctrl/bcm/Kconfig ++++ b/drivers/pinctrl/bcm/Kconfig +@@ -3,6 +3,15 @@ + # Broadcom pinctrl drivers + # + ++config PINCTRL_BCM2712 ++ bool "Broadcom BCM2712 PINCONF driver" ++ depends on OF && (ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST) ++ select PINMUX ++ select PINCONF ++ select GENERIC_PINCONF ++ help ++ Say Y here to enable the Broadcom BCM2835 GPIO driver. ++ + config PINCTRL_BCM281XX + bool "Broadcom BCM281xx pinctrl driver" + depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST) +--- a/drivers/pinctrl/bcm/Makefile ++++ b/drivers/pinctrl/bcm/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + # Broadcom pinctrl support + ++obj-$(CONFIG_PINCTRL_BCM2712) += pinctrl-bcm2712.o + obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o + obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o + obj-$(CONFIG_PINCTRL_BCM4908) += pinctrl-bcm4908.o +--- /dev/null ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2712.c +@@ -0,0 +1,1216 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for Broadcom BCM2712 GPIO units (pinctrl only) ++ * ++ * Copyright (C) 2021-3 Raspberry Pi Ltd. ++ * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren ++ * ++ * Based heavily on the BCM2835 GPIO & pinctrl driver, which was inspired by: ++ * pinctrl-nomadik.c, please see original file for copyright information ++ * pinctrl-tegra.c, please see original file for copyright information ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "pinctrl-bcm2712" ++ ++/* Register offsets */ ++ ++#define BCM2712_PULL_NONE 0 ++#define BCM2712_PULL_DOWN 1 ++#define BCM2712_PULL_UP 2 ++#define BCM2712_PULL_MASK 0x3 ++ ++#define BCM2712_FSEL_COUNT 9 ++#define BCM2712_FSEL_MASK 0xf ++ ++#define FUNC(f) \ ++ [func_##f] = #f ++#define PIN(i, f1, f2, f3, f4, f5, f6, f7, f8) \ ++ [i] = { \ ++ .funcs = { \ ++ func_##f1, \ ++ func_##f2, \ ++ func_##f3, \ ++ func_##f4, \ ++ func_##f5, \ ++ func_##f6, \ ++ func_##f7, \ ++ func_##f8, \ ++ }, \ ++ } ++ ++#define REG_BIT_INVALID 0xffff ++ ++#define BIT_TO_REG(b) (((b) >> 5) << 2) ++#define BIT_TO_SHIFT(b) ((b) & 0x1f) ++ ++#define GPIO_REGS(n, mr, mb, pr, pb) \ ++ [n] = { ((mr)*4)*8 + (mb)*4, ((pr)*4)*8 + (pb)*2 } ++ ++#define EMMC_REGS(n, r, b) \ ++ [n] = { 0, ((r)*4)*8 + (b)*2 } ++ ++#define AGPIO_REGS(n, mr, mb, pr, pb) \ ++ [n] = { ((mr)*4)*8 + (mb)*4, ((pr)*4)*8 + (pb)*2 } ++ ++#define SGPIO_REGS(n, mr, mb) \ ++ [n+32] = { ((mr)*4)*8 + (mb)*4, REG_BIT_INVALID } ++ ++#define GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a) ++#define AGPIO_PIN(a) PINCTRL_PIN(a, "aon_gpio" #a) ++#define SGPIO_PIN(a) PINCTRL_PIN(a+32, "aon_sgpio" #a) ++ ++struct pin_regs { ++ u16 mux_bit; ++ u16 pad_bit; ++}; ++ ++struct bcm2712_pinctrl { ++ struct device *dev; ++ void __iomem *base; ++ struct pinctrl_dev *pctl_dev; ++ struct pinctrl_desc pctl_desc; ++ const struct pin_regs *pin_regs; ++ const struct bcm2712_pin_funcs *pin_funcs; ++ const char *const *gpio_groups; ++ struct pinctrl_gpio_range gpio_range; ++ spinlock_t lock; ++}; ++ ++struct bcm_plat_data { ++ const struct pinctrl_desc *pctl_desc; ++ const struct pinctrl_gpio_range *gpio_range; ++ const struct pin_regs *pin_regs; ++ const struct bcm2712_pin_funcs *pin_funcs; ++}; ++ ++struct bcm2712_pin_funcs { ++ u8 funcs[BCM2712_FSEL_COUNT - 1]; ++}; ++ ++enum bcm2712_funcs { ++ func_gpio, ++ func_alt1, ++ func_alt2, ++ func_alt3, ++ func_alt4, ++ func_alt5, ++ func_alt6, ++ func_alt7, ++ func_alt8, ++ func_aon_cpu_standbyb, ++ func_aon_fp_4sec_resetb, ++ func_aon_gpclk, ++ func_aon_pwm, ++ func_arm_jtag, ++ func_aud_fs_clk0, ++ func_avs_pmu_bsc, ++ func_bsc_m0, ++ func_bsc_m1, ++ func_bsc_m2, ++ func_bsc_m3, ++ func_clk_observe, ++ func_ctl_hdmi_5v, ++ func_enet0, ++ func_enet0_mii, ++ func_enet0_rgmii, ++ func_ext_sc_clk, ++ func_fl0, ++ func_fl1, ++ func_gpclk0, ++ func_gpclk1, ++ func_gpclk2, ++ func_hdmi_tx0_auto_i2c, ++ func_hdmi_tx0_bsc, ++ func_hdmi_tx1_auto_i2c, ++ func_hdmi_tx1_bsc, ++ func_i2s_in, ++ func_i2s_out, ++ func_ir_in, ++ func_mtsif, ++ func_mtsif_alt, ++ func_mtsif_alt1, ++ func_pdm, ++ func_pkt, ++ func_pm_led_out, ++ func_sc0, ++ func_sd0, ++ func_sd2, ++ func_sd_card_a, ++ func_sd_card_b, ++ func_sd_card_c, ++ func_sd_card_d, ++ func_sd_card_e, ++ func_sd_card_f, ++ func_sd_card_g, ++ func_spdif_out, ++ func_spi_m, ++ func_spi_s, ++ func_sr_edm_sense, ++ func_te0, ++ func_te1, ++ func_tsio, ++ func_uart0, ++ func_uart1, ++ func_uart2, ++ func_usb_pwr, ++ func_usb_vbus, ++ func_uui, ++ func_vc_i2c0, ++ func_vc_i2c3, ++ func_vc_i2c4, ++ func_vc_i2c5, ++ func_vc_i2csl, ++ func_vc_pcm, ++ func_vc_pwm0, ++ func_vc_pwm1, ++ func_vc_spi0, ++ func_vc_spi3, ++ func_vc_spi4, ++ func_vc_spi5, ++ func_vc_uart0, ++ func_vc_uart2, ++ func_vc_uart3, ++ func_vc_uart4, ++ func__, ++ func_count = func__ ++}; ++ ++static const struct pin_regs bcm2712_c0_gpio_pin_regs[] = { ++ GPIO_REGS(0, 0, 0, 7, 7), ++ GPIO_REGS(1, 0, 1, 7, 8), ++ GPIO_REGS(2, 0, 2, 7, 9), ++ GPIO_REGS(3, 0, 3, 7, 10), ++ GPIO_REGS(4, 0, 4, 7, 11), ++ GPIO_REGS(5, 0, 5, 7, 12), ++ GPIO_REGS(6, 0, 6, 7, 13), ++ GPIO_REGS(7, 0, 7, 7, 14), ++ GPIO_REGS(8, 1, 0, 8, 0), ++ GPIO_REGS(9, 1, 1, 8, 1), ++ GPIO_REGS(10, 1, 2, 8, 2), ++ GPIO_REGS(11, 1, 3, 8, 3), ++ GPIO_REGS(12, 1, 4, 8, 4), ++ GPIO_REGS(13, 1, 5, 8, 5), ++ GPIO_REGS(14, 1, 6, 8, 6), ++ GPIO_REGS(15, 1, 7, 8, 7), ++ GPIO_REGS(16, 2, 0, 8, 8), ++ GPIO_REGS(17, 2, 1, 8, 9), ++ GPIO_REGS(18, 2, 2, 8, 10), ++ GPIO_REGS(19, 2, 3, 8, 11), ++ GPIO_REGS(20, 2, 4, 8, 12), ++ GPIO_REGS(21, 2, 5, 8, 13), ++ GPIO_REGS(22, 2, 6, 8, 14), ++ GPIO_REGS(23, 2, 7, 9, 0), ++ GPIO_REGS(24, 3, 0, 9, 1), ++ GPIO_REGS(25, 3, 1, 9, 2), ++ GPIO_REGS(26, 3, 2, 9, 3), ++ GPIO_REGS(27, 3, 3, 9, 4), ++ GPIO_REGS(28, 3, 4, 9, 5), ++ GPIO_REGS(29, 3, 5, 9, 6), ++ GPIO_REGS(30, 3, 6, 9, 7), ++ GPIO_REGS(31, 3, 7, 9, 8), ++ GPIO_REGS(32, 4, 0, 9, 9), ++ GPIO_REGS(33, 4, 1, 9, 10), ++ GPIO_REGS(34, 4, 2, 9, 11), ++ GPIO_REGS(35, 4, 3, 9, 12), ++ GPIO_REGS(36, 4, 4, 9, 13), ++ GPIO_REGS(37, 4, 5, 9, 14), ++ GPIO_REGS(38, 4, 6, 10, 0), ++ GPIO_REGS(39, 4, 7, 10, 1), ++ GPIO_REGS(40, 5, 0, 10, 2), ++ GPIO_REGS(41, 5, 1, 10, 3), ++ GPIO_REGS(42, 5, 2, 10, 4), ++ GPIO_REGS(43, 5, 3, 10, 5), ++ GPIO_REGS(44, 5, 4, 10, 6), ++ GPIO_REGS(45, 5, 5, 10, 7), ++ GPIO_REGS(46, 5, 6, 10, 8), ++ GPIO_REGS(47, 5, 7, 10, 9), ++ GPIO_REGS(48, 6, 0, 10, 10), ++ GPIO_REGS(49, 6, 1, 10, 11), ++ GPIO_REGS(50, 6, 2, 10, 12), ++ GPIO_REGS(51, 6, 3, 10, 13), ++ GPIO_REGS(52, 6, 4, 10, 14), ++ GPIO_REGS(53, 6, 5, 11, 0), ++ EMMC_REGS(54, 11, 1), /* EMMC_CMD */ ++ EMMC_REGS(55, 11, 2), /* EMMC_DS */ ++ EMMC_REGS(56, 11, 3), /* EMMC_CLK */ ++ EMMC_REGS(57, 11, 4), /* EMMC_DAT0 */ ++ EMMC_REGS(58, 11, 5), /* EMMC_DAT1 */ ++ EMMC_REGS(59, 11, 6), /* EMMC_DAT2 */ ++ EMMC_REGS(60, 11, 7), /* EMMC_DAT3 */ ++ EMMC_REGS(61, 11, 8), /* EMMC_DAT4 */ ++ EMMC_REGS(62, 11, 9), /* EMMC_DAT5 */ ++ EMMC_REGS(63, 11, 10), /* EMMC_DAT6 */ ++ EMMC_REGS(64, 11, 11), /* EMMC_DAT7 */ ++}; ++ ++static struct pin_regs bcm2712_c0_aon_gpio_pin_regs[] = { ++ AGPIO_REGS(0, 3, 0, 6, 10), ++ AGPIO_REGS(1, 3, 1, 6, 11), ++ AGPIO_REGS(2, 3, 2, 6, 12), ++ AGPIO_REGS(3, 3, 3, 6, 13), ++ AGPIO_REGS(4, 3, 4, 6, 14), ++ AGPIO_REGS(5, 3, 5, 7, 0), ++ AGPIO_REGS(6, 3, 6, 7, 1), ++ AGPIO_REGS(7, 3, 7, 7, 2), ++ AGPIO_REGS(8, 4, 0, 7, 3), ++ AGPIO_REGS(9, 4, 1, 7, 4), ++ AGPIO_REGS(10, 4, 2, 7, 5), ++ AGPIO_REGS(11, 4, 3, 7, 6), ++ AGPIO_REGS(12, 4, 4, 7, 7), ++ AGPIO_REGS(13, 4, 5, 7, 8), ++ AGPIO_REGS(14, 4, 6, 7, 9), ++ AGPIO_REGS(15, 4, 7, 7, 10), ++ AGPIO_REGS(16, 5, 0, 7, 11), ++ SGPIO_REGS(0, 0, 0), ++ SGPIO_REGS(1, 0, 1), ++ SGPIO_REGS(2, 0, 2), ++ SGPIO_REGS(3, 0, 3), ++ SGPIO_REGS(4, 1, 0), ++ SGPIO_REGS(5, 2, 0), ++}; ++ ++static const struct pinctrl_pin_desc bcm2712_c0_gpio_pins[] = { ++ GPIO_PIN(0), ++ GPIO_PIN(1), ++ GPIO_PIN(2), ++ GPIO_PIN(3), ++ GPIO_PIN(4), ++ GPIO_PIN(5), ++ GPIO_PIN(6), ++ GPIO_PIN(7), ++ GPIO_PIN(8), ++ GPIO_PIN(9), ++ GPIO_PIN(10), ++ GPIO_PIN(11), ++ GPIO_PIN(12), ++ GPIO_PIN(13), ++ GPIO_PIN(14), ++ GPIO_PIN(15), ++ GPIO_PIN(16), ++ GPIO_PIN(17), ++ GPIO_PIN(18), ++ GPIO_PIN(19), ++ GPIO_PIN(20), ++ GPIO_PIN(21), ++ GPIO_PIN(22), ++ GPIO_PIN(23), ++ GPIO_PIN(24), ++ GPIO_PIN(25), ++ GPIO_PIN(26), ++ GPIO_PIN(27), ++ GPIO_PIN(28), ++ GPIO_PIN(29), ++ GPIO_PIN(30), ++ GPIO_PIN(31), ++ GPIO_PIN(32), ++ GPIO_PIN(33), ++ GPIO_PIN(34), ++ GPIO_PIN(35), ++ GPIO_PIN(36), ++ GPIO_PIN(37), ++ GPIO_PIN(38), ++ GPIO_PIN(39), ++ GPIO_PIN(40), ++ GPIO_PIN(41), ++ GPIO_PIN(42), ++ GPIO_PIN(43), ++ GPIO_PIN(44), ++ GPIO_PIN(45), ++ GPIO_PIN(46), ++ GPIO_PIN(47), ++ GPIO_PIN(48), ++ GPIO_PIN(49), ++ GPIO_PIN(50), ++ GPIO_PIN(51), ++ GPIO_PIN(52), ++ GPIO_PIN(53), ++ PINCTRL_PIN(54, "emmc_cmd"), ++ PINCTRL_PIN(55, "emmc_ds"), ++ PINCTRL_PIN(56, "emmc_clk"), ++ PINCTRL_PIN(57, "emmc_dat0"), ++ PINCTRL_PIN(58, "emmc_dat1"), ++ PINCTRL_PIN(59, "emmc_dat2"), ++ PINCTRL_PIN(60, "emmc_dat3"), ++ PINCTRL_PIN(61, "emmc_dat4"), ++ PINCTRL_PIN(62, "emmc_dat5"), ++ PINCTRL_PIN(63, "emmc_dat6"), ++ PINCTRL_PIN(64, "emmc_dat7"), ++}; ++ ++static struct pinctrl_pin_desc bcm2712_c0_aon_gpio_pins[] = { ++ AGPIO_PIN(0), ++ AGPIO_PIN(1), ++ AGPIO_PIN(2), ++ AGPIO_PIN(3), ++ AGPIO_PIN(4), ++ AGPIO_PIN(5), ++ AGPIO_PIN(6), ++ AGPIO_PIN(7), ++ AGPIO_PIN(8), ++ AGPIO_PIN(9), ++ AGPIO_PIN(10), ++ AGPIO_PIN(11), ++ AGPIO_PIN(12), ++ AGPIO_PIN(13), ++ AGPIO_PIN(14), ++ AGPIO_PIN(15), ++ AGPIO_PIN(16), ++ SGPIO_PIN(0), ++ SGPIO_PIN(1), ++ SGPIO_PIN(2), ++ SGPIO_PIN(3), ++ SGPIO_PIN(4), ++ SGPIO_PIN(5), ++}; ++ ++static const struct pin_regs bcm2712_d0_gpio_pin_regs[] = { ++ GPIO_REGS(1, 0, 0, 4, 5), ++ GPIO_REGS(2, 0, 1, 4, 6), ++ GPIO_REGS(3, 0, 2, 4, 7), ++ GPIO_REGS(4, 0, 3, 4, 8), ++ GPIO_REGS(10, 0, 4, 4, 9), ++ GPIO_REGS(11, 0, 5, 4, 10), ++ GPIO_REGS(12, 0, 6, 4, 11), ++ GPIO_REGS(13, 0, 7, 4, 12), ++ GPIO_REGS(14, 1, 0, 4, 13), ++ GPIO_REGS(15, 1, 1, 4, 14), ++ GPIO_REGS(18, 1, 2, 5, 0), ++ GPIO_REGS(19, 1, 3, 5, 1), ++ GPIO_REGS(20, 1, 4, 5, 2), ++ GPIO_REGS(21, 1, 5, 5, 3), ++ GPIO_REGS(22, 1, 6, 5, 4), ++ GPIO_REGS(23, 1, 7, 5, 5), ++ GPIO_REGS(24, 2, 0, 5, 6), ++ GPIO_REGS(25, 2, 1, 5, 7), ++ GPIO_REGS(26, 2, 2, 5, 8), ++ GPIO_REGS(27, 2, 3, 5, 9), ++ GPIO_REGS(28, 2, 4, 5, 10), ++ GPIO_REGS(29, 2, 5, 5, 11), ++ GPIO_REGS(30, 2, 6, 5, 12), ++ GPIO_REGS(31, 2, 7, 5, 13), ++ GPIO_REGS(32, 3, 0, 5, 14), ++ GPIO_REGS(33, 3, 1, 6, 0), ++ GPIO_REGS(34, 3, 2, 6, 1), ++ GPIO_REGS(35, 3, 3, 6, 2), ++}; ++ ++static struct pin_regs bcm2712_d0_aon_gpio_pin_regs[] = { ++ AGPIO_REGS(0, 3, 0, 5, 9), ++ AGPIO_REGS(1, 3, 1, 5, 10), ++ AGPIO_REGS(2, 3, 2, 5, 11), ++ AGPIO_REGS(3, 3, 3, 5, 12), ++ AGPIO_REGS(4, 3, 4, 5, 13), ++ AGPIO_REGS(5, 3, 5, 5, 14), ++ AGPIO_REGS(6, 3, 6, 6, 0), ++ AGPIO_REGS(8, 3, 7, 6, 1), ++ AGPIO_REGS(9, 4, 0, 6, 2), ++ AGPIO_REGS(12, 4, 1, 6, 3), ++ AGPIO_REGS(13, 4, 2, 6, 4), ++ AGPIO_REGS(14, 4, 3, 6, 5), ++ SGPIO_REGS(0, 0, 0), ++ SGPIO_REGS(1, 0, 1), ++ SGPIO_REGS(2, 0, 2), ++ SGPIO_REGS(3, 0, 3), ++ SGPIO_REGS(4, 1, 0), ++ SGPIO_REGS(5, 2, 0), ++}; ++ ++static const struct pinctrl_pin_desc bcm2712_d0_gpio_pins[] = { ++ GPIO_PIN(1), ++ GPIO_PIN(2), ++ GPIO_PIN(3), ++ GPIO_PIN(4), ++ GPIO_PIN(10), ++ GPIO_PIN(11), ++ GPIO_PIN(12), ++ GPIO_PIN(13), ++ GPIO_PIN(14), ++ GPIO_PIN(15), ++ GPIO_PIN(18), ++ GPIO_PIN(19), ++ GPIO_PIN(20), ++ GPIO_PIN(21), ++ GPIO_PIN(22), ++ GPIO_PIN(23), ++ GPIO_PIN(24), ++ GPIO_PIN(25), ++ GPIO_PIN(26), ++ GPIO_PIN(27), ++ GPIO_PIN(28), ++ GPIO_PIN(29), ++ GPIO_PIN(30), ++ GPIO_PIN(31), ++ GPIO_PIN(32), ++ GPIO_PIN(33), ++ GPIO_PIN(34), ++ GPIO_PIN(35), ++}; ++ ++static struct pinctrl_pin_desc bcm2712_d0_aon_gpio_pins[] = { ++ AGPIO_PIN(0), ++ AGPIO_PIN(1), ++ AGPIO_PIN(2), ++ AGPIO_PIN(3), ++ AGPIO_PIN(4), ++ AGPIO_PIN(5), ++ AGPIO_PIN(6), ++ AGPIO_PIN(8), ++ AGPIO_PIN(9), ++ AGPIO_PIN(12), ++ AGPIO_PIN(13), ++ AGPIO_PIN(14), ++ SGPIO_PIN(0), ++ SGPIO_PIN(1), ++ SGPIO_PIN(2), ++ SGPIO_PIN(3), ++ SGPIO_PIN(4), ++ SGPIO_PIN(5), ++}; ++ ++static const char * const bcm2712_func_names[] = { ++ FUNC(gpio), ++ FUNC(alt1), ++ FUNC(alt2), ++ FUNC(alt3), ++ FUNC(alt4), ++ FUNC(alt5), ++ FUNC(alt6), ++ FUNC(alt7), ++ FUNC(alt8), ++ FUNC(aon_cpu_standbyb), ++ FUNC(aon_fp_4sec_resetb), ++ FUNC(aon_gpclk), ++ FUNC(aon_pwm), ++ FUNC(arm_jtag), ++ FUNC(aud_fs_clk0), ++ FUNC(avs_pmu_bsc), ++ FUNC(bsc_m0), ++ FUNC(bsc_m1), ++ FUNC(bsc_m2), ++ FUNC(bsc_m3), ++ FUNC(clk_observe), ++ FUNC(ctl_hdmi_5v), ++ FUNC(enet0), ++ FUNC(enet0_mii), ++ FUNC(enet0_rgmii), ++ FUNC(ext_sc_clk), ++ FUNC(fl0), ++ FUNC(fl1), ++ FUNC(gpclk0), ++ FUNC(gpclk1), ++ FUNC(gpclk2), ++ FUNC(hdmi_tx0_auto_i2c), ++ FUNC(hdmi_tx0_bsc), ++ FUNC(hdmi_tx1_auto_i2c), ++ FUNC(hdmi_tx1_bsc), ++ FUNC(i2s_in), ++ FUNC(i2s_out), ++ FUNC(ir_in), ++ FUNC(mtsif), ++ FUNC(mtsif_alt), ++ FUNC(mtsif_alt1), ++ FUNC(pdm), ++ FUNC(pkt), ++ FUNC(pm_led_out), ++ FUNC(sc0), ++ FUNC(sd0), ++ FUNC(sd2), ++ FUNC(sd_card_a), ++ FUNC(sd_card_b), ++ FUNC(sd_card_c), ++ FUNC(sd_card_d), ++ FUNC(sd_card_e), ++ FUNC(sd_card_f), ++ FUNC(sd_card_g), ++ FUNC(spdif_out), ++ FUNC(spi_m), ++ FUNC(spi_s), ++ FUNC(sr_edm_sense), ++ FUNC(te0), ++ FUNC(te1), ++ FUNC(tsio), ++ FUNC(uart0), ++ FUNC(uart1), ++ FUNC(uart2), ++ FUNC(usb_pwr), ++ FUNC(usb_vbus), ++ FUNC(uui), ++ FUNC(vc_i2c0), ++ FUNC(vc_i2c3), ++ FUNC(vc_i2c4), ++ FUNC(vc_i2c5), ++ FUNC(vc_i2csl), ++ FUNC(vc_pcm), ++ FUNC(vc_pwm0), ++ FUNC(vc_pwm1), ++ FUNC(vc_spi0), ++ FUNC(vc_spi3), ++ FUNC(vc_spi4), ++ FUNC(vc_spi5), ++ FUNC(vc_uart0), ++ FUNC(vc_uart2), ++ FUNC(vc_uart3), ++ FUNC(vc_uart4), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_c0_aon_gpio_pin_funcs[] = { ++ PIN(0, ir_in, vc_spi0, vc_uart3, vc_i2c3, te0, vc_i2c0, _, _), ++ PIN(1, vc_pwm0, vc_spi0, vc_uart3, vc_i2c3, te1, aon_pwm, vc_i2c0, vc_pwm1), ++ PIN(2, vc_pwm0, vc_spi0, vc_uart3, ctl_hdmi_5v, fl0, aon_pwm, ir_in, vc_pwm1), ++ PIN(3, ir_in, vc_spi0, vc_uart3, aon_fp_4sec_resetb, fl1, sd_card_g, aon_gpclk, _), ++ PIN(4, gpclk0, vc_spi0, vc_i2csl, aon_gpclk, pm_led_out, aon_pwm, sd_card_g, vc_pwm0), ++ PIN(5, gpclk1, ir_in, vc_i2csl, clk_observe, aon_pwm, sd_card_g, vc_pwm0, _), ++ PIN(6, uart1, vc_uart4, gpclk2, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _), ++ PIN(7, uart1, vc_uart4, gpclk0, aon_pwm, vc_uart0, vc_spi3, _, _), ++ PIN(8, uart1, vc_uart4, vc_i2csl, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _), ++ PIN(9, uart1, vc_uart4, vc_i2csl, aon_pwm, vc_uart0, vc_spi3, _, _), ++ PIN(10, tsio, ctl_hdmi_5v, sc0, spdif_out, vc_spi5, usb_pwr, aon_gpclk, sd_card_f), ++ PIN(11, tsio, uart0, sc0, aud_fs_clk0, vc_spi5, usb_vbus, vc_uart2, sd_card_f), ++ PIN(12, tsio, uart0, vc_uart0, tsio, vc_spi5, usb_pwr, vc_uart2, sd_card_f), ++ PIN(13, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3), ++ PIN(14, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3), ++ PIN(15, ir_in, aon_fp_4sec_resetb, vc_uart0, pm_led_out, ctl_hdmi_5v, aon_pwm, aon_gpclk, _), ++ PIN(16, aon_cpu_standbyb, gpclk0, pm_led_out, ctl_hdmi_5v, vc_pwm0, usb_pwr, aud_fs_clk0, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_c0_aon_sgpio_pin_funcs[] = { ++ PIN(0, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(1, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(2, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c4, ctl_hdmi_5v, _, _, _), ++ PIN(3, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c4, _, _, _, _), ++ PIN(4, avs_pmu_bsc, bsc_m2, vc_i2c5, ctl_hdmi_5v, _, _, _, _), ++ PIN(5, avs_pmu_bsc, bsc_m2, vc_i2c5, _, _, _, _, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_c0_gpio_pin_funcs[] = { ++ PIN(0, bsc_m3, vc_i2c0, gpclk0, enet0, vc_pwm1, vc_spi0, ir_in, _), ++ PIN(1, bsc_m3, vc_i2c0, gpclk1, enet0, vc_pwm1, sr_edm_sense, vc_spi0, vc_uart3), ++ PIN(2, pdm, i2s_in, gpclk2, vc_spi4, pkt, vc_spi0, vc_uart3, _), ++ PIN(3, pdm, i2s_in, vc_spi4, pkt, vc_spi0, vc_uart3, _, _), ++ PIN(4, pdm, i2s_in, arm_jtag, vc_spi4, pkt, vc_spi0, vc_uart3, _), ++ PIN(5, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5), ++ PIN(6, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5), ++ PIN(7, i2s_out, spdif_out, arm_jtag, sd_card_e, vc_i2c3, enet0_rgmii, vc_pcm, vc_spi4), ++ PIN(8, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, vc_i2c3, enet0_mii, vc_pcm, vc_spi4), ++ PIN(9, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, enet0_mii, sd_card_c, vc_spi4, _), ++ PIN(10, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4), ++ PIN(11, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4), ++ PIN(12, spi_s, mtsif_alt1, i2s_in, i2s_out, vc_spi5, vc_i2csl, sd0, sd_card_d), ++ PIN(13, spi_s, mtsif_alt1, i2s_out, usb_vbus, vc_spi5, vc_i2csl, sd0, sd_card_d), ++ PIN(14, spi_s, vc_i2csl, enet0_rgmii, arm_jtag, vc_spi5, vc_pwm0, vc_i2c4, sd_card_d), ++ PIN(15, spi_s, vc_i2csl, vc_spi3, arm_jtag, vc_pwm0, vc_i2c4, gpclk0, _), ++ PIN(16, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, gpclk1, _), ++ PIN(17, sd_card_b, i2s_out, vc_spi3, i2s_in, ext_sc_clk, sd0, enet0_rgmii, gpclk2), ++ PIN(18, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, vc_pwm1, _), ++ PIN(19, sd_card_b, usb_pwr, vc_spi3, pkt, spdif_out, sd0, ir_in, vc_pwm1), ++ PIN(20, sd_card_b, uui, vc_uart0, arm_jtag, uart2, usb_pwr, vc_pcm, vc_uart4), ++ PIN(21, usb_pwr, uui, vc_uart0, arm_jtag, uart2, sd_card_b, vc_pcm, vc_uart4), ++ PIN(22, usb_pwr, enet0, vc_uart0, mtsif, uart2, usb_vbus, vc_pcm, vc_i2c5), ++ PIN(23, usb_vbus, enet0, vc_uart0, mtsif, uart2, i2s_out, vc_pcm, vc_i2c5), ++ PIN(24, mtsif, pkt, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3, _), ++ PIN(25, mtsif, pkt, sc0, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3), ++ PIN(26, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _), ++ PIN(27, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _), ++ PIN(28, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _), ++ PIN(29, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _), ++ PIN(30, mtsif, pkt, sc0, sd2, enet0_rgmii, gpclk0, vc_pwm0, _), ++ PIN(31, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_pwm0, _), ++ PIN(32, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_uart3, _), ++ PIN(33, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_uart3, _, _), ++ PIN(34, mtsif, pkt, ext_sc_clk, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _), ++ PIN(35, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _, _), ++ PIN(36, sd0, mtsif, sc0, i2s_in, vc_uart3, vc_uart2, _, _), ++ PIN(37, sd0, mtsif, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _), ++ PIN(38, sd0, mtsif_alt, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _), ++ PIN(39, sd0, mtsif_alt, sc0, vc_spi0, vc_uart3, vc_uart2, _, _), ++ PIN(40, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _), ++ PIN(41, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _), ++ PIN(42, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(43, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(44, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(45, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(46, vc_spi0, mtsif_alt, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m, _), ++ PIN(47, enet0, mtsif_alt, i2s_out, mtsif_alt1, arm_jtag, _, _, _), ++ PIN(48, sc0, usb_pwr, spdif_out, mtsif, _, _, _, _), ++ PIN(49, sc0, usb_pwr, aud_fs_clk0, mtsif, _, _, _, _), ++ PIN(50, sc0, usb_vbus, sc0, _, _, _, _, _), ++ PIN(51, sc0, enet0, sc0, sr_edm_sense, _, _, _, _), ++ PIN(52, sc0, enet0, vc_pwm1, _, _, _, _, _), ++ PIN(53, sc0, enet0_rgmii, ext_sc_clk, _, _, _, _, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_d0_aon_gpio_pin_funcs[] = { ++ PIN(0, ir_in, vc_spi0, vc_uart0, vc_i2c3, uart0, vc_i2c0, _, _), ++ PIN(1, vc_pwm0, vc_spi0, vc_uart0, vc_i2c3, uart0, aon_pwm, vc_i2c0, vc_pwm1), ++ PIN(2, vc_pwm0, vc_spi0, vc_uart0, ctl_hdmi_5v, uart0, aon_pwm, ir_in, vc_pwm1), ++ PIN(3, ir_in, vc_spi0, vc_uart0, uart0, sd_card_g, aon_gpclk, _, _), ++ PIN(4, gpclk0, vc_spi0, pm_led_out, aon_pwm, sd_card_g, vc_pwm0, _, _), ++ PIN(5, gpclk1, ir_in, aon_pwm, sd_card_g, vc_pwm0, _, _, _), ++ PIN(6, uart1, vc_uart2, ctl_hdmi_5v, gpclk2, vc_spi3, _, _, _), ++ PIN(7, _, _, _, _, _, _, _, _), ++ PIN(8, uart1, vc_uart2, ctl_hdmi_5v, vc_spi0, vc_spi3, _, _, _), ++ PIN(9, uart1, vc_uart2, vc_uart0, aon_pwm, vc_spi0, vc_uart2, vc_spi3, _), ++ PIN(10, _, _, _, _, _, _, _, _), ++ PIN(11, _, _, _, _, _, _, _, _), ++ PIN(12, uart1, vc_uart2, vc_uart0, vc_spi0, usb_pwr, vc_uart2, vc_spi3, _), ++ PIN(13, bsc_m1, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3, _), ++ PIN(14, bsc_m1, aon_gpclk, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_d0_aon_sgpio_pin_funcs[] = { ++ PIN(0, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(1, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(2, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c0, ctl_hdmi_5v, _, _, _), ++ PIN(3, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c0, _, _, _, _), ++ PIN(4, avs_pmu_bsc, bsc_m2, vc_i2c3, ctl_hdmi_5v, _, _, _, _), ++ PIN(5, avs_pmu_bsc, bsc_m2, vc_i2c3, _, _, _, _, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_d0_gpio_pin_funcs[] = { ++ PIN(1, vc_i2c0, usb_pwr, gpclk0, sd_card_e, vc_spi3, sr_edm_sense, vc_spi0, vc_uart0), ++ PIN(2, vc_i2c0, usb_pwr, gpclk1, sd_card_e, vc_spi3, clk_observe, vc_spi0, vc_uart0), ++ PIN(3, vc_i2c3, usb_vbus, gpclk2, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _), ++ PIN(4, vc_i2c3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _), ++ PIN(10, bsc_m3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, gpclk0, _, _), ++ PIN(11, bsc_m3, vc_spi3, clk_observe, sd_card_c, gpclk1, _, _, _), ++ PIN(12, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _), ++ PIN(13, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _), ++ PIN(14, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, sd_card_d, _, _), ++ PIN(15, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, gpclk0, _, _), ++ PIN(18, sd_card_f, vc_pwm1, _, _, _, _, _, _), ++ PIN(19, sd_card_f, usb_pwr, vc_pwm1, _, _, _, _, _), ++ PIN(20, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _), ++ PIN(21, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _), ++ PIN(22, sd_card_f, vc_uart0, vc_i2c3, _, _, _, _, _), ++ PIN(23, vc_uart0, vc_i2c3, _, _, _, _, _, _), ++ PIN(24, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _), ++ PIN(25, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _), ++ PIN(26, sd_card_b, vc_spi0, arm_jtag, uart0, usb_vbus, vc_uart2, vc_spi0, _), ++ PIN(27, sd_card_b, vc_spi0, arm_jtag, uart0, vc_uart2, vc_spi0, _, _), ++ PIN(28, sd_card_b, vc_spi0, arm_jtag, vc_i2c0, vc_spi0, _, _, _), ++ PIN(29, arm_jtag, vc_i2c0, vc_spi0, _, _, _, _, _), ++ PIN(30, sd2, gpclk0, vc_pwm0, _, _, _, _, _), ++ PIN(31, sd2, vc_spi3, vc_pwm0, _, _, _, _, _), ++ PIN(32, sd2, vc_spi3, vc_uart3, _, _, _, _, _), ++ PIN(33, sd2, vc_spi3, vc_uart3, _, _, _, _, _), ++ PIN(34, sd2, vc_spi3, vc_i2c5, _, _, _, _, _), ++ PIN(35, sd2, vc_spi3, vc_i2c5, _, _, _, _, _), ++}; ++ ++static inline u32 bcm2712_reg_rd(struct bcm2712_pinctrl *pc, unsigned reg) ++{ ++ return readl(pc->base + reg); ++} ++ ++static inline void bcm2712_reg_wr(struct bcm2712_pinctrl *pc, unsigned reg, ++ u32 val) ++{ ++ writel(val, pc->base + reg); ++} ++ ++static enum bcm2712_funcs bcm2712_pinctrl_fsel_get( ++ struct bcm2712_pinctrl *pc, unsigned pin) ++{ ++ u32 bit = pc->pin_regs[pin].mux_bit; ++ enum bcm2712_funcs func; ++ int fsel; ++ u32 val; ++ ++ if (!bit) ++ return func_gpio; ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ fsel = (val >> BIT_TO_SHIFT(bit)) & BCM2712_FSEL_MASK; ++ func = pc->pin_funcs[pin].funcs[fsel]; ++ if (func >= func_count) ++ func = (enum bcm2712_funcs)fsel; ++ ++ dev_dbg(pc->dev, "get %04x: %08x (%u => %s)\n", ++ BIT_TO_REG(bit), val, pin, ++ bcm2712_func_names[func]); ++ ++ return func; ++} ++ ++static void bcm2712_pinctrl_fsel_set( ++ struct bcm2712_pinctrl *pc, unsigned pin, ++ enum bcm2712_funcs func) ++{ ++ u32 bit = pc->pin_regs[pin].mux_bit, val; ++ const u8 *pin_funcs; ++ unsigned long flags; ++ int fsel; ++ int cur; ++ int i; ++ ++ if (!bit || func >= func_count) ++ return; ++ ++ fsel = BCM2712_FSEL_COUNT; ++ ++ if (func >= BCM2712_FSEL_COUNT) { ++ /* Convert to an fsel number */ ++ pin_funcs = pc->pin_funcs[pin].funcs; ++ for (i = 1; i < BCM2712_FSEL_COUNT; i++) { ++ if (pin_funcs[i - 1] == func) { ++ fsel = i; ++ break; ++ } ++ } ++ } else { ++ fsel = (enum bcm2712_funcs)func; ++ } ++ if (fsel >= BCM2712_FSEL_COUNT) ++ return; ++ ++ spin_lock_irqsave(&pc->lock, flags); ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ cur = (val >> BIT_TO_SHIFT(bit)) & BCM2712_FSEL_MASK; ++ ++ dev_dbg(pc->dev, "read %04x: %08x (%u => %s)\n", ++ BIT_TO_REG(bit), val, pin, ++ bcm2712_func_names[cur]); ++ ++ if (cur != fsel) { ++ val &= ~(BCM2712_FSEL_MASK << BIT_TO_SHIFT(bit)); ++ val |= fsel << BIT_TO_SHIFT(bit); ++ ++ dev_dbg(pc->dev, "write %04x: %08x (%u <= %s)\n", ++ BIT_TO_REG(bit), val, pin, ++ bcm2712_func_names[fsel]); ++ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val); ++ } ++ ++ spin_unlock_irqrestore(&pc->lock, flags); ++} ++ ++static int bcm2712_pctl_get_groups_count(struct pinctrl_dev *pctldev) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ return pc->pctl_desc.npins; ++} ++ ++static const char *bcm2712_pctl_get_group_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ return pc->gpio_groups[selector]; ++} ++ ++static int bcm2712_pctl_get_group_pins(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const unsigned **pins, ++ unsigned *num_pins) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ *pins = &pc->pctl_desc.pins[selector].number; ++ *num_pins = 1; ++ ++ return 0; ++} ++ ++static void bcm2712_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, ++ struct seq_file *s, ++ unsigned offset) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ enum bcm2712_funcs fsel = bcm2712_pinctrl_fsel_get(pc, offset); ++ const char *fname = bcm2712_func_names[fsel]; ++ ++ seq_printf(s, "function %s", fname); ++} ++ ++static void bcm2712_pctl_dt_free_map(struct pinctrl_dev *pctldev, ++ struct pinctrl_map *maps, unsigned num_maps) ++{ ++ int i; ++ ++ for (i = 0; i < num_maps; i++) ++ if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN) ++ kfree(maps[i].data.configs.configs); ++ ++ kfree(maps); ++} ++ ++static const struct pinctrl_ops bcm2712_pctl_ops = { ++ .get_groups_count = bcm2712_pctl_get_groups_count, ++ .get_group_name = bcm2712_pctl_get_group_name, ++ .get_group_pins = bcm2712_pctl_get_group_pins, ++ .pin_dbg_show = bcm2712_pctl_pin_dbg_show, ++ .dt_node_to_map = pinconf_generic_dt_node_to_map_all, ++ .dt_free_map = bcm2712_pctl_dt_free_map, ++}; ++ ++static int bcm2712_pmx_free(struct pinctrl_dev *pctldev, ++ unsigned offset) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ /* disable by setting to GPIO */ ++ bcm2712_pinctrl_fsel_set(pc, offset, func_gpio); ++ return 0; ++} ++ ++static int bcm2712_pmx_get_functions_count(struct pinctrl_dev *pctldev) ++{ ++ return func_count; ++} ++ ++static const char *bcm2712_pmx_get_function_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ return (selector < func_count) ? bcm2712_func_names[selector] : NULL; ++} ++ ++static int bcm2712_pmx_get_function_groups(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const char * const **groups, ++ unsigned * const num_groups) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ /* every pin can do every function */ ++ *groups = pc->gpio_groups; ++ *num_groups = pc->pctl_desc.npins; ++ ++ return 0; ++} ++ ++static int bcm2712_pmx_set(struct pinctrl_dev *pctldev, ++ unsigned func_selector, ++ unsigned group_selector) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ bcm2712_pinctrl_fsel_set(pc, group_selector, func_selector); ++ ++ return 0; ++} ++static int bcm2712_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned pin) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ bcm2712_pinctrl_fsel_set(pc, pin, func_gpio); ++ ++ return 0; ++} ++ ++static void bcm2712_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned offset) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ /* disable by setting to GPIO */ ++ bcm2712_pinctrl_fsel_set(pc, offset, func_gpio); ++} ++ ++static const struct pinmux_ops bcm2712_pmx_ops = { ++ .free = bcm2712_pmx_free, ++ .get_functions_count = bcm2712_pmx_get_functions_count, ++ .get_function_name = bcm2712_pmx_get_function_name, ++ .get_function_groups = bcm2712_pmx_get_function_groups, ++ .set_mux = bcm2712_pmx_set, ++ .gpio_request_enable = bcm2712_pmx_gpio_request_enable, ++ .gpio_disable_free = bcm2712_pmx_gpio_disable_free, ++}; ++ ++static unsigned int bcm2712_pull_config_get(struct bcm2712_pinctrl *pc, ++ unsigned int pin) ++{ ++ u32 bit = pc->pin_regs[pin].pad_bit, val; ++ ++ if (unlikely(bit == REG_BIT_INVALID)) ++ return BCM2712_PULL_NONE; ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ return (val >> BIT_TO_SHIFT(bit)) & BCM2712_PULL_MASK; ++} ++ ++static void bcm2712_pull_config_set(struct bcm2712_pinctrl *pc, ++ unsigned int pin, unsigned int arg) ++{ ++ u32 bit = pc->pin_regs[pin].pad_bit, val; ++ unsigned long flags; ++ ++ if (unlikely(bit == REG_BIT_INVALID)) { ++ dev_warn(pc->dev, "can't set pulls for %s\n", pc->gpio_groups[pin]); ++ return; ++ } ++ ++ spin_lock_irqsave(&pc->lock, flags); ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ val &= ~(BCM2712_PULL_MASK << BIT_TO_SHIFT(bit)); ++ val |= (arg << BIT_TO_SHIFT(bit)); ++ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val); ++ ++ spin_unlock_irqrestore(&pc->lock, flags); ++} ++ ++static int bcm2712_pinconf_get(struct pinctrl_dev *pctldev, ++ unsigned pin, unsigned long *config) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ enum pin_config_param param = pinconf_to_config_param(*config); ++ u32 arg; ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_NONE); ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_DOWN); ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_UP); ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ *config = pinconf_to_config_packed(param, arg); ++ ++ return -ENOTSUPP; ++} ++ ++static int bcm2712_pinconf_set(struct pinctrl_dev *pctldev, ++ unsigned int pin, unsigned long *configs, ++ unsigned int num_configs) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ u32 param, arg; ++ int i; ++ ++ for (i = 0; i < num_configs; i++) { ++ param = pinconf_to_config_param(configs[i]); ++ arg = pinconf_to_config_argument(configs[i]); ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_NONE); ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_DOWN); ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_UP); ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ } /* for each config */ ++ ++ return 0; ++} ++ ++static const struct pinconf_ops bcm2712_pinconf_ops = { ++ .is_generic = true, ++ .pin_config_get = bcm2712_pinconf_get, ++ .pin_config_set = bcm2712_pinconf_set, ++}; ++ ++static const struct pinctrl_desc bcm2712_c0_pinctrl_desc = { ++ .name = "pinctrl-bcm2712", ++ .pins = bcm2712_c0_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_c0_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_desc bcm2712_c0_aon_pinctrl_desc = { ++ .name = "aon-pinctrl-bcm2712", ++ .pins = bcm2712_c0_aon_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_c0_aon_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_desc bcm2712_d0_pinctrl_desc = { ++ .name = "pinctrl-bcm2712", ++ .pins = bcm2712_d0_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_d0_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_desc bcm2712_d0_aon_pinctrl_desc = { ++ .name = "aon-pinctrl-bcm2712", ++ .pins = bcm2712_d0_aon_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_d0_aon_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_c0_pinctrl_gpio_range = { ++ .name = "pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_c0_gpio_pins), ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_c0_aon_pinctrl_gpio_range = { ++ .name = "aon-pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_c0_aon_gpio_pins), ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_d0_pinctrl_gpio_range = { ++ .name = "pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_d0_gpio_pins), ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_d0_aon_pinctrl_gpio_range = { ++ .name = "aon-pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_d0_aon_gpio_pins), ++}; ++ ++static const struct bcm_plat_data bcm2712_c0_plat_data = { ++ .pctl_desc = &bcm2712_c0_pinctrl_desc, ++ .gpio_range = &bcm2712_c0_pinctrl_gpio_range, ++ .pin_regs = bcm2712_c0_gpio_pin_regs, ++ .pin_funcs = bcm2712_c0_gpio_pin_funcs, ++}; ++ ++static const struct bcm_plat_data bcm2712_c0_aon_plat_data = { ++ .pctl_desc = &bcm2712_c0_aon_pinctrl_desc, ++ .gpio_range = &bcm2712_c0_aon_pinctrl_gpio_range, ++ .pin_regs = bcm2712_c0_aon_gpio_pin_regs, ++ .pin_funcs = bcm2712_c0_aon_gpio_pin_funcs, ++}; ++ ++static const struct bcm_plat_data bcm2712_d0_plat_data = { ++ .pctl_desc = &bcm2712_d0_pinctrl_desc, ++ .gpio_range = &bcm2712_d0_pinctrl_gpio_range, ++ .pin_regs = bcm2712_d0_gpio_pin_regs, ++ .pin_funcs = bcm2712_d0_gpio_pin_funcs, ++}; ++ ++static const struct bcm_plat_data bcm2712_d0_aon_plat_data = { ++ .pctl_desc = &bcm2712_d0_aon_pinctrl_desc, ++ .gpio_range = &bcm2712_d0_aon_pinctrl_gpio_range, ++ .pin_regs = bcm2712_d0_aon_gpio_pin_regs, ++ .pin_funcs = bcm2712_d0_aon_gpio_pin_funcs, ++}; ++ ++static const struct of_device_id bcm2712_pinctrl_match[] = { ++ { ++ .compatible = "brcm,bcm2712-pinctrl", ++ .data = &bcm2712_c0_plat_data, ++ }, ++ { ++ .compatible = "brcm,bcm2712-aon-pinctrl", ++ .data = &bcm2712_c0_aon_plat_data, ++ }, ++ ++ { ++ .compatible = "brcm,bcm2712c0-pinctrl", ++ .data = &bcm2712_c0_plat_data, ++ }, ++ { ++ .compatible = "brcm,bcm2712c0-aon-pinctrl", ++ .data = &bcm2712_c0_aon_plat_data, ++ }, ++ ++ { ++ .compatible = "brcm,bcm2712d0-pinctrl", ++ .data = &bcm2712_d0_plat_data, ++ }, ++ { ++ .compatible = "brcm,bcm2712d0-aon-pinctrl", ++ .data = &bcm2712_d0_aon_plat_data, ++ }, ++ {} ++}; ++ ++static int bcm2712_pinctrl_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ const struct bcm_plat_data *pdata; ++ const struct of_device_id *match; ++ struct bcm2712_pinctrl *pc; ++ const char **names; ++ int num_pins, i; ++ ++ match = of_match_node(bcm2712_pinctrl_match, np); ++ if (!match) ++ return -EINVAL; ++ pdata = match->data; ++ ++ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, pc); ++ pc->dev = dev; ++ spin_lock_init(&pc->lock); ++ ++ pc->base = devm_of_iomap(dev, np, 0, NULL); ++ if (IS_ERR(pc->base)) { ++ dev_err(dev, "could not get IO memory\n"); ++ return PTR_ERR(pc->base); ++ } ++ ++ pc->pctl_desc = *pdata->pctl_desc; ++ num_pins = pc->pctl_desc.npins; ++ names = devm_kmalloc_array(dev, num_pins, sizeof(const char *), ++ GFP_KERNEL); ++ if (!names) ++ return -ENOMEM; ++ for (i = 0; i < num_pins; i++) ++ names[i] = pc->pctl_desc.pins[i].name; ++ pc->gpio_groups = names; ++ pc->pin_regs = pdata->pin_regs; ++ pc->pin_funcs = pdata->pin_funcs; ++ pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); ++ if (IS_ERR(pc->pctl_dev)) ++ return PTR_ERR(pc->pctl_dev); ++ ++ pc->gpio_range = *pdata->gpio_range; ++ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); ++ ++ return 0; ++} ++ ++static struct platform_driver bcm2712_pinctrl_driver = { ++ .probe = bcm2712_pinctrl_probe, ++ .driver = { ++ .name = MODULE_NAME, ++ .of_match_table = bcm2712_pinctrl_match, ++ .suppress_bind_attrs = true, ++ }, ++}; ++builtin_platform_driver(bcm2712_pinctrl_driver); diff --git a/target/linux/bcm27xx/patches-6.1/950-0859-mmc-brcmstb-add-support-for-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0859-mmc-brcmstb-add-support-for-BCM2712.patch new file mode 100644 index 0000000000..05d403a63e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0859-mmc-brcmstb-add-support-for-BCM2712.patch @@ -0,0 +1,498 @@ +From b627647c4500d39cb026924b608841fdf4d4d7e9 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Thu, 29 Oct 2020 09:57:16 +0800 +Subject: [PATCH] mmc: brcmstb: add support for BCM2712 + +BCM2712 has an SD Express capable SDHCI implementation and uses +the SDIO CFG register block present on other STB chips. + +Add plumbing for SD Express handover and BCM2712-specific functions. + +Due to the common bus infrastructure between BCM2711 and BCM2712, +the driver also needs to implement 32-bit IO accessors. + +mmc: brcmstb: override card presence if broken-cd is set + +Not just if the card is declared as nonremovable. + +sdhci: brcmstb: align SD express switchover with SD spec v8.00 + +Part 1 of the Physical specification, figure 3-24, details the switch +sequence for cards initially probed as SD. Add a missing check for DAT2 +level after switching VDD2 on. + +sdhci: brcmstb: clean up SD Express probe and error handling + +Refactor to avoid spurious error messages in dmesg if the requisite SD +Express DT nodes aren't present. + +Signed-off-by: Jonathan Bell + +mmc: sdhci-brcmstb: only use the delay line PHY for tuneable speeds + +The MMC core has a 200MHz core clock which allows the use of DDR50 and +below without incremental phase tuning. SDR50/SDR104 and the EMMC HS200 +speeds require tuning. + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/host/Kconfig | 2 + + drivers/mmc/host/sdhci-brcmstb.c | 356 +++++++++++++++++++++++++++++++ + 2 files changed, 358 insertions(+) + +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -1082,7 +1082,9 @@ config MMC_SDHCI_BRCMSTB + tristate "Broadcom SDIO/SD/MMC support" + depends on ARCH_BRCMSTB || BMIPS_GENERIC + depends on MMC_SDHCI_PLTFM ++ select MMC_SDHCI_IO_ACCESSORS + select MMC_CQHCI ++ select OF_DYNAMIC + default y + help + This selects support for the SDIO/SD/MMC Host Controller on +--- a/drivers/mmc/host/sdhci-brcmstb.c ++++ b/drivers/mmc/host/sdhci-brcmstb.c +@@ -11,6 +11,8 @@ + #include + #include + #include ++#include ++#include + + #include "sdhci-cqhci.h" + #include "sdhci-pltfm.h" +@@ -26,18 +28,43 @@ + + #define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0) + #define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1) ++#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS BIT(2) + + #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200 + ++#define SDIO_CFG_CTRL 0x0 ++#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31) ++#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30) ++ ++#define SDIO_CFG_SD_PIN_SEL 0x44 ++#define SDIO_CFG_SD_PIN_SEL_MASK 0x3 ++#define SDIO_CFG_SD_PIN_SEL_CARD BIT(1) ++ ++#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac ++#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31) ++#define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0) ++ + struct sdhci_brcmstb_priv { + void __iomem *cfg_regs; + unsigned int flags; + struct clk *base_clk; + u32 base_freq_hz; ++ u32 shadow_cmd; ++ u32 shadow_blk; ++ bool is_cmd_shadowed; ++ bool is_blk_shadowed; ++ struct regulator *sde_1v8; ++ struct device_node *sde_pcie; ++ void *__iomem sde_ioaddr; ++ void *__iomem sde_ioaddr2; ++ struct pinctrl *pinctrl; ++ struct pinctrl_state *pins_default; ++ struct pinctrl_state *pins_sdex; + }; + + struct brcmstb_match_priv { + void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios); ++ void (*cfginit)(struct sdhci_host *host); + struct sdhci_ops *ops; + const unsigned int flags; + }; +@@ -94,6 +121,124 @@ static void sdhci_brcmstb_set_clock(stru + sdhci_enable_clk(host, clk); + } + ++#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18) ++ ++static inline u32 sdhci_brcmstb_32only_readl(struct sdhci_host *host, int reg) ++{ ++ u32 val = readl(host->ioaddr + reg); ++ ++ pr_debug("%s: readl [0x%02x] 0x%08x\n", ++ mmc_hostname(host->mmc), reg, val); ++ return val; ++} ++ ++static u16 sdhci_brcmstb_32only_readw(struct sdhci_host *host, int reg) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); ++ u32 val; ++ u16 word; ++ ++ if ((reg == SDHCI_TRANSFER_MODE) && brcmstb_priv->is_cmd_shadowed) { ++ /* Get the saved transfer mode */ ++ val = brcmstb_priv->shadow_cmd; ++ } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) && ++ brcmstb_priv->is_blk_shadowed) { ++ /* Get the saved block info */ ++ val = brcmstb_priv->shadow_blk; ++ } else { ++ val = sdhci_brcmstb_32only_readl(host, (reg & ~3)); ++ } ++ word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff; ++ return word; ++} ++ ++static u8 sdhci_brcmstb_32only_readb(struct sdhci_host *host, int reg) ++{ ++ u32 val = sdhci_brcmstb_32only_readl(host, (reg & ~3)); ++ u8 byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff; ++ return byte; ++} ++ ++static inline void sdhci_brcmstb_32only_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ pr_debug("%s: writel [0x%02x] 0x%08x\n", ++ mmc_hostname(host->mmc), reg, val); ++ ++ writel(val, host->ioaddr + reg); ++} ++ ++/* ++ * BCM2712 unfortunately carries with it a perennial bug with the SD controller ++ * register interface present on previous chips (2711/2709/2708). Accesses must ++ * be dword-sized and a read-modify-write cycle to the 32-bit registers ++ * containing the COMMAND, TRANSFER_MODE, BLOCK_SIZE and BLOCK_COUNT registers ++ * tramples the upper/lower 16 bits of data written. BCM2712 does not seem to ++ * need the extreme delay between each write as on previous chips, just the ++ * serialisation of writes to these registers in a single 32-bit operation. ++ */ ++static void sdhci_brcmstb_32only_writew(struct sdhci_host *host, u16 val, int reg) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); ++ u32 word_shift = REG_OFFSET_IN_BITS(reg); ++ u32 mask = 0xffff << word_shift; ++ u32 oldval, newval; ++ ++ if (reg == SDHCI_COMMAND) { ++ /* Write the block now as we are issuing a command */ ++ if (brcmstb_priv->is_blk_shadowed) { ++ sdhci_brcmstb_32only_writel(host, brcmstb_priv->shadow_blk, ++ SDHCI_BLOCK_SIZE); ++ brcmstb_priv->is_blk_shadowed = false; ++ } ++ oldval = brcmstb_priv->shadow_cmd; ++ brcmstb_priv->is_cmd_shadowed = false; ++ } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) && ++ brcmstb_priv->is_blk_shadowed) { ++ /* Block size and count are stored in shadow reg */ ++ oldval = brcmstb_priv->shadow_blk; ++ } else { ++ /* Read reg, all other registers are not shadowed */ ++ oldval = sdhci_brcmstb_32only_readl(host, (reg & ~3)); ++ } ++ newval = (oldval & ~mask) | (val << word_shift); ++ ++ if (reg == SDHCI_TRANSFER_MODE) { ++ /* Save the transfer mode until the command is issued */ ++ brcmstb_priv->shadow_cmd = newval; ++ brcmstb_priv->is_cmd_shadowed = true; ++ } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) { ++ /* Save the block info until the command is issued */ ++ brcmstb_priv->shadow_blk = newval; ++ brcmstb_priv->is_blk_shadowed = true; ++ } else { ++ /* Command or other regular 32-bit write */ ++ sdhci_brcmstb_32only_writel(host, newval, reg & ~3); ++ } ++} ++ ++static void sdhci_brcmstb_32only_writeb(struct sdhci_host *host, u8 val, int reg) ++{ ++ u32 oldval = sdhci_brcmstb_32only_readl(host, (reg & ~3)); ++ u32 byte_shift = REG_OFFSET_IN_BITS(reg); ++ u32 mask = 0xff << byte_shift; ++ u32 newval = (oldval & ~mask) | (val << byte_shift); ++ ++ sdhci_brcmstb_32only_writel(host, newval, reg & ~3); ++} ++ ++static void sdhci_brcmstb_set_power(struct sdhci_host *host, unsigned char mode, ++ unsigned short vdd) ++{ ++ if (!IS_ERR(host->mmc->supply.vmmc)) { ++ struct mmc_host *mmc = host->mmc; ++ ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); ++ } ++ sdhci_set_power_noreg(host, mode, vdd); ++} ++ + static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host, + unsigned int timing) + { +@@ -123,6 +268,146 @@ static void sdhci_brcmstb_set_uhs_signal + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + } + ++static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); ++ bool want_dll = false; ++ u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104); ++ u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR | ++ MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V); ++ u32 reg; ++ ++ if (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)) { ++ if((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask)) ++ want_dll = true; ++ } ++ ++ /* ++ * If we want a speed that requires tuning, ++ * then select the delay line PHY as the clock source. ++ */ ++ if (want_dll) { ++ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE); ++ reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE; ++ reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE; ++ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE); ++ } ++ ++ if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) || ++ (host->mmc->caps & MMC_CAP_NEEDS_POLL)) { ++ /* Force presence */ ++ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL); ++ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV; ++ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN; ++ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL); ++ } else { ++ /* Enable card detection line */ ++ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL); ++ reg &= ~SDIO_CFG_SD_PIN_SEL_MASK; ++ reg |= SDIO_CFG_SD_PIN_SEL_CARD; ++ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL); ++ } ++} ++ ++static int bcm2712_init_sd_express(struct sdhci_host *host, struct mmc_ios *ios) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); ++ struct device *dev = host->mmc->parent; ++ u32 ctrl_val; ++ u32 present_state; ++ int ret; ++ ++ if (!brcmstb_priv->sde_ioaddr || !brcmstb_priv->sde_ioaddr2) ++ return -EINVAL; ++ ++ if (!brcmstb_priv->pinctrl) ++ return -EINVAL; ++ ++ /* Turn off the SD clock first */ ++ sdhci_set_clock(host, 0); ++ ++ /* Disable SD DAT0-3 pulls */ ++ pinctrl_select_state(brcmstb_priv->pinctrl, brcmstb_priv->pins_sdex); ++ ++ ctrl_val = readl(brcmstb_priv->sde_ioaddr); ++ dev_dbg(dev, "ctrl_val 1 %08x\n", ctrl_val); ++ ++ /* Tri-state the SD pins */ ++ ctrl_val |= 0x1ff8; ++ writel(ctrl_val, brcmstb_priv->sde_ioaddr); ++ dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr)); ++ /* Let voltages settle */ ++ udelay(100); ++ ++ /* Enable the PCIe sideband pins */ ++ ctrl_val &= ~0x6000; ++ writel(ctrl_val, brcmstb_priv->sde_ioaddr); ++ dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr)); ++ /* Let voltages settle */ ++ udelay(100); ++ ++ /* Turn on the 1v8 VDD2 regulator */ ++ ret = regulator_enable(brcmstb_priv->sde_1v8); ++ if (ret) ++ return ret; ++ ++ /* Wait for Tpvcrl */ ++ msleep(1); ++ ++ /* Sample DAT2 (CLKREQ#) - if low, card is in PCIe mode */ ++ present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); ++ present_state = (present_state & SDHCI_DATA_LVL_MASK) >> SDHCI_DATA_LVL_SHIFT; ++ dev_dbg(dev, "state = 0x%08x\n", present_state); ++ ++ if (present_state & BIT(2)) { ++ dev_err(dev, "DAT2 still high, abandoning SDex switch\n"); ++ return -ENODEV; ++ } ++ ++ /* Turn on the LCPLL PTEST mux */ ++ ctrl_val = readl(brcmstb_priv->sde_ioaddr2 + 20); // misc5 ++ ctrl_val &= ~(0x7 << 7); ++ ctrl_val |= 3 << 7; ++ writel(ctrl_val, brcmstb_priv->sde_ioaddr2 + 20); ++ dev_dbg(dev, "misc 5->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2 + 20)); ++ ++ /* PTEST diff driver enable */ ++ ctrl_val = readl(brcmstb_priv->sde_ioaddr2); ++ ctrl_val |= BIT(21); ++ writel(ctrl_val, brcmstb_priv->sde_ioaddr2); ++ ++ dev_dbg(dev, "misc 0->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2)); ++ ++ /* Wait for more than the minimum Tpvpgl time */ ++ msleep(100); ++ ++ if (brcmstb_priv->sde_pcie) { ++ struct of_changeset changeset; ++ static struct property okay_property = { ++ .name = "status", ++ .value = "okay", ++ .length = 5, ++ }; ++ ++ /* Enable the pcie controller */ ++ of_changeset_init(&changeset); ++ ret = of_changeset_update_property(&changeset, ++ brcmstb_priv->sde_pcie, ++ &okay_property); ++ if (ret) { ++ dev_err(dev, "%s: failed to update property - %d\n", __func__, ++ ret); ++ return -ENODEV; ++ } ++ ret = of_changeset_apply(&changeset); ++ } ++ ++ dev_dbg(dev, "%s -> %d\n", __func__, ret); ++ return ret; ++} ++ + static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc) + { + sdhci_dumpregs(mmc_priv(mmc)); +@@ -155,6 +440,21 @@ static struct sdhci_ops sdhci_brcmstb_op + .set_uhs_signaling = sdhci_set_uhs_signaling, + }; + ++static struct sdhci_ops sdhci_brcmstb_ops_2712 = { ++ .read_l = sdhci_brcmstb_32only_readl, ++ .read_w = sdhci_brcmstb_32only_readw, ++ .read_b = sdhci_brcmstb_32only_readb, ++ .write_l = sdhci_brcmstb_32only_writel, ++ .write_w = sdhci_brcmstb_32only_writew, ++ .write_b = sdhci_brcmstb_32only_writeb, ++ .set_clock = sdhci_set_clock, ++ .set_power = sdhci_brcmstb_set_power, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++ .init_sd_express = bcm2712_init_sd_express, ++}; ++ + static struct sdhci_ops sdhci_brcmstb_ops_7216 = { + .set_clock = sdhci_brcmstb_set_clock, + .set_bus_width = sdhci_set_bus_width, +@@ -179,10 +479,16 @@ static const struct brcmstb_match_priv m + .ops = &sdhci_brcmstb_ops_7216, + }; + ++static const struct brcmstb_match_priv match_priv_2712 = { ++ .cfginit = sdhci_brcmstb_cfginit_2712, ++ .ops = &sdhci_brcmstb_ops_2712, ++}; ++ + static const struct of_device_id sdhci_brcm_of_match[] = { + { .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 }, + { .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 }, + { .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 }, ++ { .compatible = "brcm,bcm2712-sdhci", .data = &match_priv_2712 }, + {}, + }; + +@@ -256,6 +562,7 @@ static int sdhci_brcmstb_probe(struct pl + u32 actual_clock_mhz; + struct sdhci_host *host; + struct resource *iomem; ++ bool no_pinctrl = false; + struct clk *clk; + struct clk *base_clk = NULL; + int res; +@@ -290,6 +597,11 @@ static int sdhci_brcmstb_probe(struct pl + match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; + } + ++ priv->sde_pcie = of_parse_phandle(pdev->dev.of_node, ++ "sde-pcie", 0); ++ if (priv->sde_pcie) ++ priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; ++ + /* Map in the non-standard CFG registers */ + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + priv->cfg_regs = devm_ioremap_resource(&pdev->dev, iomem); +@@ -303,6 +615,43 @@ static int sdhci_brcmstb_probe(struct pl + if (res) + goto err; + ++ priv->sde_1v8 = devm_regulator_get_optional(&pdev->dev, "sde-1v8"); ++ if (IS_ERR(priv->sde_1v8)) ++ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (iomem) { ++ priv->sde_ioaddr = devm_ioremap_resource(&pdev->dev, iomem); ++ if (IS_ERR(priv->sde_ioaddr)) ++ priv->sde_ioaddr = NULL; ++ } ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 3); ++ if (iomem) { ++ priv->sde_ioaddr2 = devm_ioremap_resource(&pdev->dev, iomem); ++ if (IS_ERR(priv->sde_ioaddr2)) ++ priv->sde_ioaddr = NULL; ++ } ++ ++ priv->pinctrl = devm_pinctrl_get(&pdev->dev); ++ if (IS_ERR(priv->pinctrl)) { ++ no_pinctrl = true; ++ } ++ priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default"); ++ if (IS_ERR(priv->pins_default)) { ++ dev_dbg(&pdev->dev, "No pinctrl default state\n"); ++ no_pinctrl = true; ++ } ++ priv->pins_sdex = pinctrl_lookup_state(priv->pinctrl, "sd-express"); ++ if (IS_ERR(priv->pins_sdex)) { ++ dev_dbg(&pdev->dev, "No pinctrl sd-express state\n"); ++ no_pinctrl = true; ++ } ++ if (no_pinctrl || !priv->sde_ioaddr || !priv->sde_ioaddr2) { ++ priv->pinctrl = NULL; ++ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; ++ } ++ + /* + * Automatic clock gating does not work for SD cards that may + * voltage switch so only enable it for non-removable devices. +@@ -319,6 +668,13 @@ static int sdhci_brcmstb_probe(struct pl + (host->mmc->caps2 & MMC_CAP2_HS400_ES)) + host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es; + ++ if (host->ops->init_sd_express && ++ (priv->flags & BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS)) ++ host->mmc->caps2 |= MMC_CAP2_SD_EXP; ++ ++ if(match_priv->cfginit) ++ match_priv->cfginit(host); ++ + /* + * Supply the existing CAPS, but clear the UHS modes. This + * will allow these modes to be specified by device tree diff --git a/target/linux/bcm27xx/patches-6.1/950-0860-sdhci-Add-SD-Express-hook.patch b/target/linux/bcm27xx/patches-6.1/950-0860-sdhci-Add-SD-Express-hook.patch new file mode 100644 index 0000000000..1aea0b3bcd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0860-sdhci-Add-SD-Express-hook.patch @@ -0,0 +1,90 @@ +From 9564939f1a92e5f9807461539de28c50e5bee440 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 6 Jul 2021 09:45:36 +0100 +Subject: [PATCH] sdhci: Add SD Express hook + +sdhci: remove PYA0_INTR_BUG quirk. Add quirks to disable some of the higher SDR speeds at 1.8v. +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 5 ++++- + drivers/mmc/host/sdhci.c | 19 +++++++++++++++++++ + drivers/mmc/host/sdhci.h | 6 ++++++ + 3 files changed, 29 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -363,7 +363,10 @@ static const struct sdhci_pltfm_data sdh + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | +- SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, ++ SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | ++ SDHCI_QUIRK2_NO_SDR50 | ++ SDHCI_QUIRK2_NO_SDR104 | ++ SDHCI_QUIRK2_NO_SDR25, + }; + + static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -3071,6 +3071,15 @@ static void sdhci_card_event(struct mmc_ + spin_unlock_irqrestore(&host->lock, flags); + } + ++static int sdhci_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct sdhci_host *host = mmc_priv(mmc); ++ ++ if (!host->ops->init_sd_express) ++ return -EOPNOTSUPP; ++ return host->ops->init_sd_express(host, ios); ++} ++ + static const struct mmc_host_ops sdhci_ops = { + .request = sdhci_request, + .post_req = sdhci_post_req, +@@ -3086,6 +3095,7 @@ static const struct mmc_host_ops sdhci_o + .execute_tuning = sdhci_execute_tuning, + .card_event = sdhci_card_event, + .card_busy = sdhci_card_busy, ++ .init_sd_express = sdhci_init_sd_express, + }; + + /*****************************************************************************\ +@@ -4605,6 +4615,15 @@ int sdhci_setup_host(struct sdhci_host * + !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) + mmc->caps |= MMC_CAP_UHS_DDR50; + ++ if (host->quirks2 & SDHCI_QUIRK2_NO_SDR25) ++ mmc->caps &= ~MMC_CAP_UHS_SDR25; ++ ++ if (host->quirks2 & SDHCI_QUIRK2_NO_SDR50) ++ mmc->caps &= ~MMC_CAP_UHS_SDR50; ++ ++ if (host->quirks2 & SDHCI_QUIRK2_NO_SDR104) ++ mmc->caps &= ~MMC_CAP_UHS_SDR104; ++ + /* Does the host need tuning for SDR50? */ + if (host->caps1 & SDHCI_USE_SDR50_TUNING) + host->flags |= SDHCI_SDR50_NEEDS_TUNING; +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -481,6 +481,11 @@ struct sdhci_host { + /* Issue CMD and DATA reset together */ + #define SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1<<19) + ++/* Quirks to ignore a speed if a that speed is unreliable */ ++#define SDHCI_QUIRK2_NO_SDR25 (1<<19) ++#define SDHCI_QUIRK2_NO_SDR50 (1<<20) ++#define SDHCI_QUIRK2_NO_SDR104 (1<<21) ++ + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ + phys_addr_t mapbase; /* physical address base */ +@@ -663,6 +668,7 @@ struct sdhci_ops { + void (*request_done)(struct sdhci_host *host, + struct mmc_request *mrq); + void (*dump_vendor_regs)(struct sdhci_host *host); ++ int (*init_sd_express)(struct sdhci_host *host, struct mmc_ios *ios); + }; + + #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS diff --git a/target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch b/target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch new file mode 100644 index 0000000000..2ac7b7830c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch @@ -0,0 +1,3788 @@ +From ce14be51d71bf39893786d380cbb82e81d2a10d5 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 14 Jul 2021 09:32:49 +0100 +Subject: [PATCH] Add new "pispbe" driver (though not yet the Makesfiles or DT + required to use it) + +media: bcm2712: Initial commit of the PiSP BE driver + +Signed-off-by: Naushir Patuck + +media: bcm2712_pisp_be: PiSP driver updates. + +- Start registering video nodes from /dev/video20 +- Formatting fixes +- Define MODULE_DEVICE_TABLE() to probe correctly + +Signed-off-by: Naushir Patuck + +media: pisp_be: Improve image format support + +Add a new format table that lists the V4L2 format enums and their properties. +Keep the exising 'RPBP' format to support the userland verification tools. +This format requires userland to fill all plane properties. Standard V4L2 +formats will derive these properties from the format table. + +Signed-off-by: Naushir Patuck + +media: pisp_be: Advertise the meta output format explictily. + +Signed-off-by: Naushir Patuck + +drivers: pisp_be: Various updates and cleanups + +- Switch to a single node group for now. +- Add a node description table to simplify node handling. +- Switch HoG output to V4L2_CAP_META_CAPTURE type. +- Use string descriptions for node names in logging messages. + +Signed-off-by: Naushir Patuck + +pisp_be: Updates for libcamera usage: + +- Remove indexes from device entity names +- Add enumframesize and enumfmts ioctls +- Add default format to all nodes. + +Signed-off-by: Naushir Patuck + +v4l2: pisp_be: Move format definitions into v4l2 core + +Signed-off-by: Naushir Patuck + +media: raspberrypi: Move PiSP common headers to a single location + +Signed-off-by: Naushir Patuck + +media: raspberrypi: Remove old pispbe driver. + +This is now supersede by the driver in drivers/media/platform/raspberrypi/ + +Signed-off-by: Naushir Patuck + +PISP-BE Driver: Automate buffer-cycling for TDN and Stitch state. +Remove "tdn-input" and "stitch-input" nodes altogether (the output +nodes must still be opened and REQBUFS called with 1 or 2 buffers). +Also, a bit of tidying of buffer address handling and locking. + +PISP-BE driver: Turn debug level right down to reduce overly-chatty messages + +media: bcm2712: Depend on CONFIG_PM + +Depend on CONFIG_PM as the driver uses the runtime_pm infrastructure. + +Signed-off-by: Jacopo Mondi + +drivers: media: pisp_be: Move BE driver to a raspberrypi directory + +Move the pisp_be driver from drivers/media/platform/raspberrypi/ to +drivers/media/platform/raspberrypi/pisp_be/. This seems the accepted +convention in the drivers/media/platform/ directory structure. + +Also rename the driver module from bcm2712_pisp_be to pisp_be. + +Signed-off-by: Naushir Patuck + +pisp_be: Updates for libcamera streaming: + +- Add some required v4l2 formats +- Add buf_prepare ioctl +- Set plane offsets correctly before reprogramming + +pisp_be: Reduce logging verbosity + +Signed-off-by: Naushir Patuck + +pisp_be: Add buffer timestamps + +While at it, remove duplicate code when checking if the HW has completed +multiple jobs. + +Signed-off-by: Naushir Patuck + +pisp_be: Remove queue size allocation constraint + +PISP-BE driver: Fix ISR to handle multiple done/start events. + +PISP-BE: Fix variable-name shadowing bugette + +PISP-BE: Support for two node groups. Reorganize the driver. + +To support 2 concurrent libcamera applications, we need 2 node groups, +need to allow multiple opens of each node (because libcamera does this) +and create a separate media device per group (to support file-locking). + +This triggered significant rearrangement of the driver. Some calls +that we formerly intercepted have been delegated back to v4l2/vb2. +Logging changes arising from multiple v4l2_dev. Refactored probe() +and initialization. Avoid dynamically-allocated entity name strings. + +drivers: media: pisp_be: Add vidioc_enum_fmt_meta_out + +This was missing in the struct v4l2_ioctl_ops definition. + +Signed-off-by: Naushir Patuck + +drivers: media: pispe_be: Add Bayer compressed formats + +Add PiSP Bayer compressed formats to the list of supported pixel formats +for the PiSP backend driver. + +Signed-off-by: Naushir Patuck + +drivers: meida: pisp_be: Fix overflow in plane size calculations + +The calculations for buffer plane sizes can overflow because of the +plane factor shift. Fix this by using u64 integers for the calculations. + +Signed-off-by: Naushir Patuck + +drivers: media: pisp_be: Use 0P3 for plane factors + +Use less precision for the plane factors to avoid any nasty overflows. + +Signed-off-by: Naushir Patuck + +media: pisp: Checkpatch and coding style fixups + +Signed-off-by: Dave Stevenson + +media: pisp_be: More coding style fixups + +media: platform: bcm2712: pisp_be: Fix crash when buffer format not set + +Signed-off-by: Nick Hollinghurst + +media: platform: bcm2712: pisp_be: Allow non-SRGB colour spaces on RGB outputs + +Allow colour spaces other than SRGB when the output format in question +is an RGB output. This commit merely ports over existing changes from +the vc4 ISP driver. + +Signed-off-by: David Plowman + +media: platform: bcm2712: Tweak list of BE supported image formats + +Remove RGB565 and 10- and 12-bit packed raw formats, which ISP-BE +can't support for input or output. Add NV12M and NV21M which it can. +(I didn't bother adding YUV422P, which apparently is not widely used.) + +Signed-off-by: Nick Hollinghurst + +pisp_be: Fill the hardware revision in the media entity struct + +This can be used by userland to determine the hardware capabilities. + +Signed-off-by: Naushir Patuck + +bcm2712: Use BIT() macro + +Use the BIT() macro instead of plain bit shifting. + +Signed-off-by: Jacopo Mondi + +bcm2712: Invert condition in pispbe_schedule_internal() + +Return earlier and save one indentation level + +Signed-off-by: Jacopo Mondi + +bcm2712: Invert condition in for loop + +Save one indentation level by continuing if the node is not streaming. + +Signed-off-by: Jacopo Mondi + +bcm2712: Do not declare a local variable + +There already is a truct pispbe_node *node in the function scope. + +Signed-off-by: Jacopo Mondi + +bcm21712: Siplify pispbe_schedule_one() + +A little more verbose but easier to follow ? + +Signed-off-by: Jacopo Mondi + +bcm2712: Rename pispbe_schedule_all() to pispbe_schedule_any() + +The pispbe_schedule_all() function name is misleading, as the function +schedule a single job from any of the node groups. Rename it. + +Signed-off-by: Jacopo Mondi + +media: platform: bcm2712: Remove buffer auto-cycling from ISP-BE + +Previously, the ISP-BE driver tried to automate "ping pong" buffers +for TDN and HDR state, but did not fully conceal them from users. + +The automation has been removed: there are now separate output and +capture queues for each of TDN and Stitch, which must be managed by +user code (DMABUFs may be used to circulate buffers between queues). + +Signed-off-by: Nick Hollinghurst + +drivers: media: pisp_be: Cache BE config buffer vaddr + +When programming a new job, we access at the config buffer, possibly +from ISR context. So fetch and the virtual address when queuing the +buffer. + +Signed-off-by: Naushir Patuck + +drivers: media: pisp_be: Remove all traces of ctrls and request API + +These APIs are not (and will not) be used by the driver, so remove them. + +Signed-off-by: Naushir Patuck + +media: bcm2712: Replace v4l2_dbg with dev_dbg + +Replace the v4l2 debug helpers with the device debug once, which are +preferred. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Remove of_match_ptr() + +The of_match_ptr() usage could cause a compiler warning if +CONFIG_OF is not enabled, as the pispbe_of_match variable would +result unused. + +As the of_match_table field of struct platform_driver exists +unconditionally, drop of_match_ptr() to avoid a warning. + +Signed-off-by: Jacopo Mondi + +drivers: media: pispbe: Add local config buffer DMA allocation + +When initialiasing the driver, allocate a number of tiles + config +structures used for storing hardware config internally in the driver. + +Signed-off-by: Naushir Patuck + +drivers: media: pispbe: Use local config buffers + +Store a copy of the config + tiles buffer locally when the buffer gets +queued. This resolves the security issue where a userland process may +modify the config buffer after it has been queued. + +Signed-off-by: Naushir Patuck + +drivers: media: pispbe: Validate config buffers + +Perform a basic config validation on the device output nodes to ensure +the buffer size and stride values do not result in a buffer overrun. + +Signed-off-by: Naushir Patuck + +media: bcm2712: Rework probe sequence order + +Rework the probe sequence to: +1) Use dev_err_probe() when failing to get clocks +2) Disable clock on error path +3) Disable the node groups if they have been enabled and + propagate the error up + +Also disable clocks in the remove() function. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Use pm_runtime_ops + +Introduce usage of runtime resume and suspend operations. + +The diver only uses a single clock source which is enable/disabled +at resume and suspend time. + +Implement file open and release operations to control enablement of +the clock provider. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Demote info message + +Demote info message about clock enablement to dev_dbg() + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Move pm_runtime calls to streamon/streamoff + +Move the calls to pm_runtime_resume_and_get() and pm_runtime_put() +to the streamon and streamoff ioctl handlers. + +Remove custom handlers for the open and close file operations and use +the framework provided helpers. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Use pm_runtime_autosuspend() + +Use the _autosuspend() version of runtime_pm_put() in order to avoid +resuming and suspending the peripheral in between streaming sessions +closely apart one from the other. + +Signed-off-by: Jacopo Mondi + +drivers: media: pisp_be: Conditionally check buffers when preparing jobs + +When preparing a job, check the global enables in the config structure +to see if the Output0/1, Tdn and Stitch blocks are enabled, and only +test for a buffer queued if they are. + +This will allow userland to control the outputs selectively without +disabling/re-enabling the respective device nodes. + +Signed-off-by: Naushir Patuck + +media: bcm2712: Rework media controller registration + +The current implementation register the v4l2_device and the video +devices first, then creates the media controller and manually registers +entities there. + +Rework the registration procedure to first create the v4l2_device and +register the media_device with it. Then create the video nodes which +gets automatically registered in the media graph by the core. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Create v4l2_subdev for ISP entity + +Create a v4l2 subdevice to represent the PISPBE ISP entity. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix v4l2-compliance warn on QUERYCAP + +Fix: + +warn: v4l2-compliance.cpp(669): media bus_info +'platform:1000880000.pisp_be' differs from V4L2 bus_info +'platform:pispbe' + +by populating the driver caps bus_info by using dev_name(). + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix v4l2-compliance warn on invalid pixfmt + +The V4L2 API for the TRY_FMT/S_FMT ioctl allows the ioctl handler to +return an error code only in specific conditions. If an invalid pixel +format is supplied it should be adjusted instead of an error being +returned. + +Albeit, v4l2-compliance treats this situation as a warning and not as +an error because the behaviour has been discussed in length in the past. + +warn: v4l2-test-formats.cpp(794): TRY_FMT cannot handle an invalid pixelformat. +warn: v4l2-test-formats.cpp(795): This may or may not be a problem. For more information see: +warn: v4l2-test-formats.cpp(796): http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html +VIDIOC_TRY_FMT returned -1 (Invalid argument) + +Regardless of the warning vs failure decision, adjust the try_format() +function implementation to use V4L2_PIX_FMT_YUV420M as default pixel +format if the supplied one is invalid. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix v4l2-compliance warn on HOG pix format + +The try_format() implementation for the HOG video device node returns +an error if the supplied pixel format is not correct. + +As per the video device output and capture video nodes, this contradicts +the V4L2 specification even if it is treated as a warning by +v4l2-compliance. + +Fix this by forcing the buffer pixel format and size to the default +supported one. While at here, use the BIT() macro in the format +initialization function. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix formats enumeration + +Right now a single implementation of enum_fmt() is used for all nodes +in a group. This means that all the BE supported formats are listed for +all the nodes. This is incorrect as the meta capture and output node +formats should be restricted, and the meta formats should not be +enumerated for video output and capture devices. + +Fix this by restricting the enumeration of META formats to the config +and hog nodes. Split out from the list of supported_formats the +V4L2_META_FMT_RPI_BE_CFG which is only used for the meta_out node, while +V4L2_PIX_FMT_RPI_BE is kept in the list of supported_formats as it can +be used as an opaque format for both meta_cap, video_cap and video_out +nodes. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Minor fixes to support PiSP regression tests + +Allow RGB input, not just Bayer (but only of those at once); +Allow Wallpaper image formats. XXX They are not yet size-checked; +Set "chicken bits" to test BURST_TRIM and AXI AWID/BID variation. +Convert some v4l2_err() to dev_err() + +Signed-off-by: Nick Hollinghurst + +drivers: media: pisp_be: Use the maximum number of config buffers + +Set PISP_BE_NUM_CONFIG_BUFFERS the the maximum number of possible +buffers. In the worst case, this overallocates config buffers, but +given their size, it's not too much of a problem. + +Signed-off-by: Naushir Patuck + +media: pisp_be: Fix extra PM runtime put + +vidioc_streamoff callback can be called even if vidioc_streamon was +never called. The driver currently does PM runtime get/put in these +callbacks, which may lead to a put without a matching get. + +Fix this by moving the PM runtime get/put to vb2_ops's start_streaming & +stop_streaming, which the framework makes sure won't get extra calls. + +Signed-off-by: Tomi Valkeinen + +drivers: media: pisp_be: Don't report V4L2_PIX_FMT_RPI_BE format + +This is an internal opaque format, not to be reported in enum_fmt. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/Kconfig | 1 + + drivers/media/platform/Makefile | 1 + + drivers/media/platform/raspberrypi/Kconfig | 5 + + drivers/media/platform/raspberrypi/Makefile | 3 + + .../platform/raspberrypi/pisp_be/Kconfig | 12 + + .../platform/raspberrypi/pisp_be/Makefile | 6 + + .../platform/raspberrypi/pisp_be/pisp_be.c | 1985 +++++++++++++++++ + .../raspberrypi/pisp_be/pisp_be_config.h | 533 +++++ + .../raspberrypi/pisp_be/pisp_be_formats.h | 469 ++++ + drivers/media/v4l2-core/v4l2-ioctl.c | 2 + + include/media/raspberrypi/pisp_common.h | 65 + + include/media/raspberrypi/pisp_types.h | 144 ++ + include/uapi/linux/videodev2.h | 6 + + 13 files changed, 3232 insertions(+) + create mode 100644 drivers/media/platform/raspberrypi/Kconfig + create mode 100644 drivers/media/platform/raspberrypi/Makefile + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/Kconfig + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/Makefile + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/pisp_be.c + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h + create mode 100644 include/media/raspberrypi/pisp_common.h + create mode 100644 include/media/raspberrypi/pisp_types.h + +--- a/drivers/media/platform/Kconfig ++++ b/drivers/media/platform/Kconfig +@@ -76,6 +76,7 @@ source "drivers/media/platform/mediatek/ + source "drivers/media/platform/nvidia/Kconfig" + source "drivers/media/platform/nxp/Kconfig" + source "drivers/media/platform/qcom/Kconfig" ++source "drivers/media/platform/raspberrypi/Kconfig" + source "drivers/media/platform/renesas/Kconfig" + source "drivers/media/platform/rockchip/Kconfig" + source "drivers/media/platform/samsung/Kconfig" +--- a/drivers/media/platform/Makefile ++++ b/drivers/media/platform/Makefile +@@ -19,6 +19,7 @@ obj-y += mediatek/ + obj-y += nvidia/ + obj-y += nxp/ + obj-y += qcom/ ++obj-y += raspberrypi/ + obj-y += renesas/ + obj-y += rockchip/ + obj-y += samsung/ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++comment "Raspberry Pi media platform drivers" ++ ++source "drivers/media/platform/raspberrypi/pisp_be/Kconfig" +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += pisp_be/ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/Kconfig +@@ -0,0 +1,12 @@ ++config VIDEO_RASPBERRYPI_PISP_BE ++ tristate "Raspberry Pi PiSP Backend (BE) ISP driver" ++ depends on VIDEO_DEV && PM ++ 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. ++ ++ To compile this driver as a module, choose M here. The module will be ++ called pisp-be. +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for Raspberry Pi PiSP Backend driver ++# ++pisp-be-objs := pisp_be.o ++obj-$(CONFIG_VIDEO_RASPBERRYPI_PISP_BE) += pisp-be.o +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +@@ -0,0 +1,1985 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * PiSP Back End driver. ++ * Copyright (c) 2021-2022 Raspberry Pi Limited. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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"); ++ ++/* 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 ++ ++/* ++ * 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_2712C1 0x02252700 ++#define PISP_BE_VERSION_MINOR_BITS 0xF ++ ++/* ++ * This maps our nodes onto the inputs/outputs of the actual PiSP Back End. ++ * Be wary of the word "OUTPUT" which is used ambiguously here. In a V4L2 ++ * context it means an input to the hardware (source image or metadata). ++ * Elsewhere it means an output from the hardware. ++ */ ++enum node_ids { ++ MAIN_INPUT_NODE, ++ TDN_INPUT_NODE, ++ STITCH_INPUT_NODE, ++ HOG_OUTPUT_NODE, ++ OUTPUT0_NODE, ++ OUTPUT1_NODE, ++ TDN_OUTPUT_NODE, ++ STITCH_OUTPUT_NODE, ++ CONFIG_NODE, ++ PISPBE_NUM_NODES ++}; ++ ++struct 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] = { ++ /* MAIN_INPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-input", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, ++ .caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE, ++ }, ++ /* TDN_INPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-tdn_input", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, ++ .caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE, ++ }, ++ /* STITCH_INPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-stitch_input", ++ .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", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* OUTPUT1_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-output1", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* TDN_OUTPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-tdn_output", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* STITCH_OUTPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-stitch_output", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* CONFIG_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-config", ++ .buf_type = V4L2_BUF_TYPE_META_OUTPUT, ++ .caps = V4L2_CAP_META_OUTPUT, ++ } ++}; ++ ++#define NODE_DESC_IS_OUTPUT(desc) ( \ ++ ((desc)->buf_type == V4L2_BUF_TYPE_META_OUTPUT) || \ ++ ((desc)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || \ ++ ((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)) ++#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) ( \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) || \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) ++ ++/* ++ * Structure to describe a single node /dev/video which represents a single ++ * input or output queue to the PiSP Back End device. ++ */ ++struct pispbe_node { ++ unsigned int id; ++ int vfl_dir; ++ enum v4l2_buf_type buf_type; ++ struct video_device vfd; ++ struct media_pad pad; ++ struct media_intf_devnode *intf_devnode; ++ struct media_link *intf_link; ++ struct pispbe_node_group *node_group; ++ struct mutex node_lock; ++ struct mutex queue_lock; ++ spinlock_t ready_lock; ++ struct list_head ready_queue; ++ struct vb2_queue queue; ++ struct v4l2_format format; ++ const struct pisp_be_format *pisp_format; ++}; ++ ++/* 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; ++}; ++ ++/* Records details of the jobs currently running or queued on the h/w. */ ++struct pispbe_job { ++ struct pispbe_node_group *node_group; ++ /* ++ * An array of buffer pointers - remember it's source buffers first, ++ * then captures, then metadata last. ++ */ ++ struct pispbe_buffer *buf[PISPBE_NUM_NODES]; ++}; ++ ++/* ++ * Structure representing the entire PiSP Back End device, comprising several ++ * node groups 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; ++ void __iomem *be_reg_base; ++ struct clk *clk; ++ 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) ++{ ++ return readl(pispbe->be_reg_base + offset); ++} ++ ++static inline void write_reg(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) ++{ ++ unsigned int begin, end; ++ unsigned int u; ++ ++ if (read_reg(pispbe, PISP_BE_STATUS_OFFSET) & 1) ++ dev_err(pispbe->dev, "ERROR: not safe to queue new job!\n"); ++ ++ /* ++ * Write configuration to hardware. DMA addresses and enable flags ++ * are passed separately, because the driver needs to sanitize them, ++ * 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]); ++ ++ /* ++ * Everything else is as supplied by the user. XXX Buffer sizes not ++ * checked! ++ */ ++ 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); ++ } ++ ++ /* 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, ++ "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_reg(pispbe, PISP_BE_TILE_ADDR_LO_OFFSET, (u32)tiles); ++ write_reg(pispbe, PISP_BE_TILE_ADDR_HI_OFFSET, (u32)(tiles >> 32)); ++ ++ /* Enqueue the job */ ++ write_reg(pispbe, PISP_BE_CONTROL_OFFSET, 3 + 65536 * num_tiles); ++} ++ ++struct pispbe_buffer { ++ struct vb2_v4l2_buffer vb; ++ struct list_head ready_list; ++ unsigned int config_index; ++}; ++ ++static int get_addr_3(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; ++ unsigned int size; ++ unsigned int p; ++ ++ 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; ++ ++ for (p = 0; p < num_planes && p < 3; 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++) { ++ /* ++ * Calculate the address offset of this plane as needed ++ * by the hardware. This is specifically for non-mplane ++ * buffer formats, where there are 3 image planes, e.g. ++ * for the V4L2_PIX_FMT_YUV420 format. ++ */ ++ addr[p] = addr[0] + ((size * plane_factor) >> 3); ++ plane_factor += node->pisp_format->plane_factor[p]; ++ } ++ ++ return num_planes; ++} ++ ++static dma_addr_t 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; ++ ++ /* 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; ++ ++ /* ++ * 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]); ++ 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; ++ return; ++ } ++ ++ /* ++ * Now TDN/Stitch inputs and outputs. These are single-plane and only ++ * 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 (addrs[3] == 0 || ++ !(hw_enables[0] & PISP_BE_BAYER_ENABLE_TDN_INPUT) || ++ !(hw_enables[0] & 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); ++ if (!(config->config.tdn.reset & 1)) ++ hw_enables[0] &= ~PISP_BE_BAYER_ENABLE_TDN; ++ } ++ ++ addrs[4] = 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] &= ++ ~(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]); ++ if (addrs[5] == 0) ++ hw_enables[0] &= ~(PISP_BE_BAYER_ENABLE_TDN_COMPRESS | ++ PISP_BE_BAYER_ENABLE_TDN_OUTPUT); ++ ++ addrs[6] = get_addr(buf[STITCH_OUTPUT_NODE]); ++ if (addrs[6] == 0) ++ hw_enables[0] &= ++ ~(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; ++ } ++ ++ /* 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]); ++ if (ret <= 0) ++ hw_enables[1] &= ~(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. ++ * ++ * Warning: needs to be called with hw_lock taken, and releases it if it ++ * schedules a job. ++ */ ++static int pispbe_schedule_internal(struct pispbe_node_group *node_group, ++ unsigned long flags) ++{ ++ 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; ++ unsigned int config_index; ++ int i; ++ ++ /* ++ * 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; ++ } ++ ++ 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); ++ ++ /* Exit early if no config buffer has been queued. */ ++ if (!buf[CONFIG_NODE]) ++ return 0; ++ ++ 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); ++ ++ /* remember: srcimages, captures then metadata */ ++ for (i = 0; i < PISPBE_NUM_NODES; i++) { ++ unsigned int bayer_en = ++ config_tiles_buffer->config.global.bayer_enables; ++ unsigned int rgb_en = ++ config_tiles_buffer->config.global.rgb_enables; ++ bool ignore_buffers = false; ++ ++ /* Config node is handled outside the loop above. */ ++ if (i == CONFIG_NODE) ++ continue; ++ ++ buf[i] = NULL; ++ if (!(node_group->streaming_map & BIT(i))) ++ continue; ++ ++ if ((!(rgb_en & PISP_BE_RGB_ENABLE_OUTPUT0) && ++ i == OUTPUT0_NODE) || ++ (!(rgb_en & PISP_BE_RGB_ENABLE_OUTPUT1) && ++ i == OUTPUT1_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_TDN_INPUT) && ++ i == TDN_INPUT_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_TDN_OUTPUT) && ++ i == TDN_OUTPUT_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_STITCH_INPUT) && ++ i == STITCH_INPUT_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_STITCH_OUTPUT) && ++ i == STITCH_OUTPUT_NODE)) { ++ /* ++ * Ignore Output0/Output1/Tdn/Stitch buffer check if the ++ * 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]; ++ ++ spin_lock_irqsave(&node->ready_lock, flags1); ++ 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.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"); ++ ++ /* 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); ++ ++ return 1; ++} ++ ++/* 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; ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ if (pispbe->hw_busy) { ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ return; ++ } ++ ++ /* 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); ++} ++ ++/* Try and schedule a job for any of the node groups. */ ++static void pispbe_schedule_any(struct pispbe_dev *pispbe, int clear_hw_busy) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ ++ if (clear_hw_busy) ++ pispbe->hw_busy = 0; ++ if (pispbe->hw_busy == 0) { ++ unsigned int i; ++ ++ 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; ++ } ++ } ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++} ++ ++static void pispbe_isr_jobdone(struct pispbe_dev *pispbe, ++ struct pispbe_job *job) ++{ ++ struct pispbe_buffer **buf = job->buf; ++ u64 ts = ktime_get_ns(); ++ int i; ++ ++ for (i = 0; i < PISPBE_NUM_NODES; i++) { ++ if (buf[i]) { ++ buf[i]->vb.vb2_buf.timestamp = ts; ++ vb2_buffer_done(&buf[i]->vb.vb2_buf, ++ VB2_BUF_STATE_DONE); ++ } ++ } ++} ++ ++static irqreturn_t pispbe_isr(int irq, void *dev) ++{ ++ struct pispbe_dev *pispbe = (struct pispbe_dev *)dev; ++ u8 started, done; ++ int can_queue_another = 0; ++ u32 u; ++ ++ u = read_reg(pispbe, PISP_BE_INTERRUPT_STATUS_OFFSET); ++ 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); ++ 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) { ++ 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) { ++ pispbe_isr_jobdone(pispbe, &pispbe->queued_job); ++ pispbe->done++; ++ dev_dbg(pispbe->dev, "Job done (2)\n"); ++ } else { ++ pispbe->running_job = pispbe->queued_job; ++ } ++ ++ memset(&pispbe->queued_job, 0, sizeof(pispbe->queued_job)); ++ } ++ ++ if (pispbe->done != done || pispbe->started != started) { ++ dev_err(pispbe->dev, "PROBLEM: counters not matching!\n"); ++ pispbe->started = started; ++ pispbe->done = done; ++ } ++ ++ /* check if there's more to do before going to sleep */ ++ pispbe_schedule_any(pispbe, can_queue_another); ++ ++ return IRQ_HANDLED; ++} ++ ++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 = node_group->pispbe->dev; ++ struct v4l2_format *fmt; ++ unsigned int bpl, size, i, j; ++ ++ 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__); ++ return -EIO; ++ } ++ ++ /* Ensure output config strides and buffer sizes match the V4L2 formats. */ ++ 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; ++ if (fmt->fmt.pix_mp.plane_fmt[0].bytesperline < bpl) { ++ dev_err(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", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ ++ 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; ++ if (fmt->fmt.pix_mp.plane_fmt[0].bytesperline < bpl) { ++ dev_err(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", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ ++ for (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++) { ++ 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; ++ ++ 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", ++ __func__, j); ++ return -EINVAL; ++ } ++ if (fmt->fmt.pix_mp.plane_fmt[i].sizeimage < size) { ++ dev_err(dev, "%s: size mismatch on output\n", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int pispbe_node_queue_setup(struct vb2_queue *q, unsigned int *nbuffers, ++ unsigned int *nplanes, unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct pispbe_node *node = vb2_get_drv_priv(q); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ *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); ++ 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); ++ } ++ ++ dev_dbg(pispbe->dev, ++ "Image (or metadata) size %u, nbuffers %u for node %s\n", ++ sizes[0], *nbuffers, NODE_NAME(node)); ++ ++ return 0; ++} ++ ++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; ++ unsigned int num_planes = NODE_IS_MPLANE(node) ? ++ node->format.fmt.pix_mp.num_planes : 1; ++ unsigned int i; ++ ++ 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; ++ ++ if (vb2_plane_size(vb, i) < size) { ++ dev_err(pispbe->dev, ++ "data will not fit into plane %d (%lu < %lu)\n", ++ i, vb2_plane_size(vb, i), size); ++ return -EINVAL; ++ } ++ ++ vb2_set_plane_payload(vb, i, size); ++ } ++ ++ if (node->id == CONFIG_NODE) { ++ 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(node->node_group, dst); ++ } ++ ++ return 0; ++} ++ ++static void pispbe_node_buffer_queue(struct vb2_buffer *buf) ++{ ++ struct vb2_v4l2_buffer *vbuf = ++ container_of(buf, struct vb2_v4l2_buffer, vb2_buf); ++ 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; ++ unsigned long flags; ++ ++ dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node)); ++ spin_lock_irqsave(&node->ready_lock, flags); ++ list_add_tail(&buffer->ready_list, &node->ready_queue); ++ spin_unlock_irqrestore(&node->ready_lock, flags); ++ ++ /* ++ * Every time we add a buffer, check if there's now some work for the hw ++ * to do, but only for this client. ++ */ ++ pispbe_schedule_one(node_group); ++} ++ ++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; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(pispbe->dev); ++ if (ret < 0) ++ return ret; ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ node->node_group->streaming_map |= BIT(node->id); ++ 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); ++ ++ /* Maybe we're ready to run. */ ++ pispbe_schedule_one(node_group); ++ ++ return 0; ++} ++ ++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_buffer *buf; ++ unsigned long flags; ++ ++ /* ++ * Now this is a bit awkward. In a simple M2M device we could just wait ++ * for all queued jobs to complete, but here there's a risk that a ++ * 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. ++ */ ++ dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node)); ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ do { ++ unsigned long flags1; ++ ++ spin_lock_irqsave(&node->ready_lock, flags1); ++ buf = list_first_entry_or_null(&node->ready_queue, ++ struct pispbe_buffer, ++ ready_list); ++ if (buf) { ++ list_del(&buf->ready_list); ++ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); ++ } ++ spin_unlock_irqrestore(&node->ready_lock, flags1); ++ } while (buf); ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ vb2_wait_for_all_buffers(&node->queue); ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ 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 for this group now 0x%x\n", ++ node_group->streaming_map); ++} ++ ++static const struct vb2_ops pispbe_node_queue_ops = { ++ .queue_setup = pispbe_node_queue_setup, ++ .buf_prepare = pispbe_node_buffer_prepare, ++ .buf_queue = pispbe_node_buffer_queue, ++ .start_streaming = pispbe_node_start_streaming, ++ .stop_streaming = pispbe_node_stop_streaming, ++}; ++ ++static const struct v4l2_file_operations pispbe_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = vb2_fop_release, ++ .poll = vb2_fop_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = vb2_fop_mmap ++}; ++ ++static int pispbe_node_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->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; ++} ++ ++static int pispbe_node_g_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; ++ ++ if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { ++ dev_err(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; ++} ++ ++static int pispbe_node_g_fmt_vid_out(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_CAPTURE(node) || NODE_IS_META(node)) { ++ dev_err(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; ++} ++ ++static int pispbe_node_g_fmt_meta_out(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_CAPTURE(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 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) ++{ ++ 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; ++ } ++ ++ return NULL; ++} ++ ++static void 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++) ++ total_plane_factor += fmt->plane_factor[i]; ++ ++ for (i = 0; i < nplanes; i++) { ++ struct v4l2_plane_pix_format *p = &f->fmt.pix_mp.plane_fmt[i]; ++ unsigned int bpl, plane_size; ++ ++ bpl = (f->fmt.pix_mp.width * fmt->bit_depth) >> 3; ++ bpl = ALIGN(max(p->bytesperline, bpl), fmt->align); ++ ++ plane_size = bpl * f->fmt.pix_mp.height * ++ (nplanes > 1 ? fmt->plane_factor[i] : total_plane_factor); ++ /* ++ * The shift is to divide out the plane_factor fixed point ++ * scaling of 8. ++ */ ++ plane_size = max(p->sizeimage, plane_size >> 3); ++ ++ p->bytesperline = bpl; ++ p->sizeimage = plane_size; ++ } ++} ++ ++static int try_format(struct v4l2_format *f, struct pispbe_node *node) ++{ ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ 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", ++ __func__, NODE_NAME(node), f->fmt.pix_mp.width, ++ f->fmt.pix_mp.height, V4L2_FOURCC_CONV_ARGS(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); ++ if (!fmt) ++ fmt = find_format(V4L2_PIX_FMT_YUV420M); ++ ++ f->fmt.pix_mp.pixelformat = fmt->fourcc; ++ f->fmt.pix_mp.num_planes = fmt->num_planes; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ f->fmt.pix_mp.width = max(min(f->fmt.pix_mp.width, 65536u), ++ PISP_BACK_END_MIN_TILE_WIDTH); ++ f->fmt.pix_mp.height = max(min(f->fmt.pix_mp.height, 65536u), ++ PISP_BACK_END_MIN_TILE_HEIGHT); ++ ++ /* ++ * Fill in the actual colour space when the requested one was ++ * 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)) ++ f->fmt.pix_mp.colorspace = fmt->colorspace_default; ++ ++ /* In all cases, we only support the defaults for these: */ ++ f->fmt.pix_mp.ycbcr_enc = ++ V4L2_MAP_YCBCR_ENC_DEFAULT(f->fmt.pix_mp.colorspace); ++ f->fmt.pix_mp.xfer_func = ++ V4L2_MAP_XFER_FUNC_DEFAULT(f->fmt.pix_mp.colorspace); ++ ++ is_rgb = f->fmt.pix_mp.colorspace == V4L2_COLORSPACE_SRGB; ++ f->fmt.pix_mp.quantization = ++ V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, f->fmt.pix_mp.colorspace, ++ f->fmt.pix_mp.ycbcr_enc); ++ ++ /* Set plane size and bytes/line for each plane. */ ++ set_plane_params(f, fmt); ++ ++ for (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, ++ f->fmt.pix_mp.height, fmt->bit_depth, ++ 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; ++ ++ if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { ++ dev_err(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; ++ ++ return 0; ++} ++ ++static int pispbe_node_try_fmt_vid_out(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; ++ ++ if (!NODE_IS_OUTPUT(node) || NODE_IS_META(node)) { ++ dev_err(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; ++ ++ return 0; ++} ++ ++static int pispbe_node_try_fmt_meta_out(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_CAPTURE(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_META_FMT_RPI_BE_CFG; ++ f->fmt.meta.buffersize = sizeof(struct pisp_be_tiles_config); ++ ++ 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); ++ ++ if (ret < 0) ++ return ret; ++ ++ node->format = *f; ++ node->pisp_format = find_format(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; ++} ++ ++static int pispbe_node_s_fmt_vid_out(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_out(file, priv, f); ++ ++ if (ret < 0) ++ return ret; ++ ++ node->format = *f; ++ node->pisp_format = find_format(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; ++} ++ ++static int pispbe_node_s_fmt_meta_out(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_out(file, priv, f); ++ ++ if (ret < 0) ++ return ret; ++ ++ 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 capture 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_enum_fmt(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ ++ if (f->type != node->queue.type) ++ return -EINVAL; ++ ++ if (NODE_IS_META(node)) { ++ 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->flags = 0; ++ return 0; ++ } ++ ++ if (f->index >= ARRAY_SIZE(supported_formats)) ++ return -EINVAL; ++ ++ f->pixelformat = supported_formats[f->index].fourcc; ++ f->flags = 0; ++ ++ return 0; ++} ++ ++static int pispbe_enum_framesizes(struct file *file, void *priv, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->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", ++ fsize->pixel_format); ++ return -EINVAL; ++ } ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise.min_width = 32; ++ fsize->stepwise.max_width = 65535; ++ fsize->stepwise.step_width = 2; ++ ++ fsize->stepwise.min_height = 32; ++ fsize->stepwise.max_height = 65535; ++ fsize->stepwise.step_height = 2; ++ ++ 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, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_streamon = pispbe_node_streamon, ++ .vidioc_streamoff = pispbe_node_streamoff, ++}; ++ ++static const struct video_device pispbe_videodev = { ++ .name = PISPBE_NAME, ++ .vfl_dir = VFL_DIR_M2M, /* gets overwritten */ ++ .fops = &pispbe_fops, ++ .ioctl_ops = &pispbe_node_ioctl_ops, ++ .minor = -1, ++ .release = video_device_release_empty, ++}; ++ ++static void node_set_default_format(struct pispbe_node *node) ++{ ++ if (NODE_IS_META(node) && NODE_IS_OUTPUT(node)) { ++ /* Config node */ ++ struct v4l2_format *f = &node->format; ++ ++ 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_YUV420M; ++ f.fmt.pix_mp.width = 1920; ++ f.fmt.pix_mp.height = 1080; ++ f.type = node->buf_type; ++ try_format(&f, node); ++ node->format = f; ++ } ++ ++ node->pisp_format = find_format(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) ++{ ++ 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 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->buf_type = node_desc[id].buf_type; ++ ++ mutex_init(&node->node_lock); ++ mutex_init(&node->queue_lock); ++ INIT_LIST_HEAD(&node->ready_queue); ++ spin_lock_init(&node->ready_lock); ++ ++ node->format.type = node->buf_type; ++ node_set_default_format(node); ++ ++ q->type = node->buf_type; ++ q->io_modes = VB2_MMAP | VB2_DMABUF; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->drv_priv = node; ++ 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; ++ /* 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; ++ } ++ ++ *vdev = pispbe_videodev; /* default initialization */ ++ strscpy(vdev->name, node_desc[id].ent_name, sizeof(vdev->name)); ++ 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; ++ vdev->queue = &node->queue; ++ vdev->device_caps = V4L2_CAP_STREAMING | node_desc[id].caps; ++ ++ node->pad.flags = output ? MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK; ++ ret = media_entity_pads_init(entity, 1, &node->pad); ++ if (ret) { ++ dev_err(pispbe->dev, ++ "Failed to register media pads for %s device node\n", ++ NODE_NAME(node)); ++ goto err_unregister_queue; ++ } ++ ++ 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", ++ NODE_NAME(node)); ++ goto err_unregister_queue; ++ } ++ video_set_drvdata(vdev, node); ++ ++ if (output) ++ 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(&node_group->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); ++ return 0; ++ ++err_unregister_video_dev: ++ video_unregister_device(&node->vfd); ++err_unregister_queue: ++ vb2_queue_release(&node->queue); ++ return ret; ++} ++ ++static const struct v4l2_subdev_pad_ops pispbe_pad_ops = { ++ .link_validate = v4l2_subdev_link_validate_default, ++}; ++ ++static const struct v4l2_subdev_ops pispbe_sd_ops = { ++ .pad = &pispbe_pad_ops, ++}; ++ ++static int pispbe_init_subdev(struct pispbe_node_group *node_group) ++{ ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ struct v4l2_subdev *sd = &node_group->sd; ++ unsigned int i; ++ int ret; ++ ++ v4l2_subdev_init(sd, &pispbe_sd_ops); ++ sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; ++ sd->owner = THIS_MODULE; ++ 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 = ++ 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); ++ if (ret) ++ goto error; ++ ++ ret = v4l2_device_register_subdev(&node_group->v4l2_dev, sd); ++ if (ret) ++ goto error; ++ ++ return 0; ++ ++error: ++ media_entity_cleanup(&sd->entity); ++ return ret; ++} ++ ++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_registered = 0; ++ 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; ++ 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; ++ strscpy(v4l2_dev->name, PISPBE_NAME, sizeof(v4l2_dev->name)); ++ ++ 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(node_group); ++ 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); ++ if (ret) ++ goto err_unregister_nodes; ++ } ++ ++ ret = media_device_register(mdev); ++ if (ret) ++ goto err_unregister_nodes; ++ ++ node_group->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) { ++ dev_err(pispbe->dev, "Unable to allocate cached config buffers.\n"); ++ ret = -ENOMEM; ++ goto err_unregister_mdev; ++ } ++ ++ return 0; ++ ++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); ++ } ++ 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: ++ media_device_cleanup(mdev); ++ return ret; ++} ++ ++static void pispbe_destroy_node_group(struct pispbe_node_group *node_group) ++{ ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ int i; ++ ++ if (node_group->config) { ++ dma_free_coherent(node_group->pispbe->dev, ++ sizeof(struct pisp_be_tiles_config) * ++ PISP_BE_NUM_CONFIG_BUFFERS, ++ node_group->config, ++ node_group->config_dma_addr); ++ } ++ ++ dev_info(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); ++ ++ 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); ++ } ++ ++ media_device_cleanup(&node_group->mdev); ++ v4l2_device_unregister(&node_group->v4l2_dev); ++} ++ ++static int pispbe_runtime_suspend(struct device *dev) ++{ ++ struct pispbe_dev *pispbe = dev_get_drvdata(dev); ++ ++ clk_disable_unprepare(pispbe->clk); ++ ++ return 0; ++} ++ ++static int pispbe_runtime_resume(struct device *dev) ++{ ++ struct pispbe_dev *pispbe = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = clk_prepare_enable(pispbe->clk); ++ if (ret) { ++ dev_err(dev, "Unable to enable clock\n"); ++ return ret; ++ } ++ ++ dev_dbg(dev, "%s: Enabled clock, rate=%lu\n", ++ __func__, clk_get_rate(pispbe->clk)); ++ ++ 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_probe(struct platform_device *pdev) ++{ ++ unsigned int num_groups = 0; ++ struct pispbe_dev *pispbe; ++ int ret; ++ ++ pispbe = devm_kzalloc(&pdev->dev, sizeof(*pispbe), GFP_KERNEL); ++ if (!pispbe) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&pdev->dev, pispbe); ++ pispbe->dev = &pdev->dev; ++ platform_set_drvdata(pdev, pispbe); ++ ++ pispbe->be_reg_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(pispbe->be_reg_base)) { ++ dev_err(&pdev->dev, "Failed to get ISP-BE registers address\n"); ++ return PTR_ERR(pispbe->be_reg_base); ++ } ++ ++ pispbe->irq = platform_get_irq(pdev, 0); ++ if (pispbe->irq <= 0) { ++ dev_err(&pdev->dev, "No IRQ resource\n"); ++ return -EINVAL; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, pispbe->irq, pispbe_isr, 0, ++ PISPBE_NAME, pispbe); ++ if (ret) { ++ dev_err(&pdev->dev, "Unable to request interrupt\n"); ++ return ret; ++ } ++ ++ ret = dma_set_mask_and_coherent(pispbe->dev, DMA_BIT_MASK(36)); ++ if (ret) ++ return ret; ++ ++ pispbe->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pispbe->clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pispbe->clk), ++ "Failed to get clock"); ++ ++ /* Hardware initialisation */ ++ pm_runtime_set_autosuspend_delay(pispbe->dev, 200); ++ pm_runtime_use_autosuspend(pispbe->dev); ++ pm_runtime_enable(pispbe->dev); ++ ++ ret = pm_runtime_resume_and_get(pispbe->dev); ++ if (ret) ++ goto pm_runtime_disable_err; ++ ++ pispbe->hw_busy = 0; ++ spin_lock_init(&pispbe->hw_lock); ++ ret = hw_init(pispbe); ++ if (ret) ++ goto pm_runtime_put_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_nodes_err: ++ while (num_groups-- > 0) ++ pispbe_destroy_node_group(&pispbe->node_group[num_groups]); ++pm_runtime_put_err: ++ pm_runtime_put(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]); ++ ++ pm_runtime_dont_use_autosuspend(pispbe->dev); ++ pm_runtime_disable(pispbe->dev); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops pispbe_pm_ops = { ++ SET_RUNTIME_PM_OPS(pispbe_runtime_suspend, pispbe_runtime_resume, NULL) ++}; ++ ++static const struct of_device_id pispbe_of_match[] = { ++ { ++ .compatible = "raspberrypi,pispbe", ++ }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, pispbe_of_match); ++ ++static struct platform_driver pispbe_pdrv = { ++ .probe = pispbe_probe, ++ .remove = pispbe_remove, ++ .driver = { ++ .name = PISPBE_NAME, ++ .of_match_table = pispbe_of_match, ++ .pm = &pispbe_pm_ops, ++ }, ++}; ++ ++module_platform_driver(pispbe_pdrv); +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h +@@ -0,0 +1,533 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * 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_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +@@ -0,0 +1,469 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * PiSP Back End driver image format definitions. ++ * ++ * Copyright (c) 2021 Raspberry Pi Ltd ++ */ ++ ++#ifndef _PISP_BE_FORMATS_ ++#define _PISP_BE_FORMATS_ ++ ++#include ++#include ++ ++#define 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 num_planes; ++ unsigned int colorspace_mask; ++ enum v4l2_colorspace colorspace_default; ++}; ++ ++#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) ++ ++/* ++ * All three colour spaces JPEG, 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 ++ * outputs, program the colour spaces on them to be the same, matching whatever ++ * is requested for the low resolution output, even if the main output is ++ * 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 | \ ++ V4L2_COLORSPACE_MASK_REC709) ++ ++static const struct pisp_be_format supported_formats[] = { ++ /* Single plane YUV formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_YUV420, ++ /* 128 alignment to ensure U/V planes are 64 byte aligned. */ ++ .align = 128, ++ .bit_depth = 8, ++ .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, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU420, ++ /* 128 alignment to ensure U/V planes are 64 byte aligned. */ ++ .align = 128, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.25), P3(0.25) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV21, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ /* Multiplane YUV formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_YUV420M, ++ .align = 64, ++ .bit_depth = 8, ++ .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, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV12M, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 2, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV21M, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 2, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU420M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.25), P3(0.25) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUV422M, ++ .align = 64, ++ .bit_depth = 8, ++ .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, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU422M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5), P3(0.5) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUV444M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(1), P3(1) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU444M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(1), P3(1) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ /* RGB formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_RGB24, ++ .align = 32, ++ .bit_depth = 24, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_BGR24, ++ .align = 32, ++ .bit_depth = 24, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_XBGR32, ++ .align = 64, ++ .bit_depth = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGBX32, ++ .align = 64, ++ .bit_depth = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ /* Bayer formats - 8-bit */ ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ /* Bayer formats - 16-bit */ ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ /* Bayer formats unpacked to 16bpp */ ++ /* 10 bit */ ++ .fourcc = V4L2_PIX_FMT_SRGGB10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ /* 12 bit */ ++ .fourcc = V4L2_PIX_FMT_SRGGB12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ /* 14 bit */ ++ .fourcc = V4L2_PIX_FMT_SRGGB14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ /* Bayer formats - 16-bit PiSP Compressed */ ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++}; ++ ++static const struct pisp_be_format meta_out_supported_formats[] = { ++ /* Configuration buffer format. */ ++ { ++ .fourcc = V4L2_META_FMT_RPI_BE_CFG, ++ }, ++}; ++ ++#endif /* _PISP_BE_FORMATS_ */ +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1452,6 +1452,7 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_NV12M_10BE_8L128: descr = "10-bit NV12M (8x128 Linear, BE)"; break; + case V4L2_META_FMT_SENSOR_DATA: descr = "Sensor Ancillary Metadata"; break; + case V4L2_META_FMT_BCM2835_ISP_STATS: descr = "BCM2835 ISP Image Statistics"; break; ++ case V4L2_META_FMT_RPI_BE_CFG: descr = "PiSP Config format"; break; + + default: + /* Compressed formats */ +@@ -1503,6 +1504,7 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_MT21C: descr = "Mediatek Compressed Format"; break; + case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break; + case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break; ++ case V4L2_PIX_FMT_RPI_BE: descr = "PiSP Opaque Format"; break; + default: + if (fmt->description[0]) + return; +--- /dev/null ++++ b/include/media/raspberrypi/pisp_common.h +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Raspberry Pi PiSP common configuration definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi (Trading) Ltd. ++ * ++ */ ++#ifndef _PISP_COMMON_H_ ++#define _PISP_COMMON_H_ ++ ++#include ++ ++#include "pisp_types.h" ++ ++struct pisp_bla_config { ++ uint16_t black_level_r; ++ uint16_t black_level_gr; ++ uint16_t black_level_gb; ++ uint16_t black_level_b; ++ uint16_t output_black_level; ++ uint8_t pad[2]; ++}; ++ ++struct pisp_wbg_config { ++ uint16_t gain_r; ++ uint16_t gain_g; ++ uint16_t gain_b; ++ uint8_t pad[2]; ++}; ++ ++struct pisp_compress_config { ++ /* value subtracted from incoming data */ ++ uint16_t offset; ++ uint8_t pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ uint8_t mode; ++}; ++ ++struct pisp_decompress_config { ++ /* value added to reconstructed data */ ++ uint16_t offset; ++ uint8_t pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ uint8_t mode; ++}; ++ ++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 */ ++ uint8_t maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields, echoed on AXI bus */ ++ uint8_t cache_prot; ++ /* QoS field(s) (4x4 bits for FE writer; 4 bits for other masters) */ ++ uint16_t qos; ++}; ++ ++#endif /* _PISP_COMMON_H_ */ +--- /dev/null ++++ b/include/media/raspberrypi/pisp_types.h +@@ -0,0 +1,144 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Raspberry Pi PiSP common types. ++ * ++ * Copyright (C) 2021 - Raspberry Pi (Trading) Ltd. ++ * ++ */ ++#ifndef _PISP_TYPES_H_ ++#define _PISP_TYPES_H_ ++ ++/* This definition must match the format description in the hardware exactly! */ ++struct pisp_image_format_config { ++ /* size in pixels */ ++ uint16_t width, height; ++ /* must match struct pisp_image_format below */ ++ uint32_t format; ++ int32_t stride; ++ /* some planar image formats will need a second stride */ ++ int32_t stride2; ++}; ++ ++static_assert(sizeof(struct pisp_image_format_config) == 16); ++ ++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 ++ ++#endif /* _PISP_TYPES_H_ */ +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -793,6 +793,9 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_IPU3_SGRBG10 v4l2_fourcc('i', 'p', '3', 'G') /* IPU3 packed 10-bit GRBG bayer */ + #define V4L2_PIX_FMT_IPU3_SRGGB10 v4l2_fourcc('i', 'p', '3', 'r') /* IPU3 packed 10-bit RGGB bayer */ + ++/* The pixel format for all our buffers (the precise format is found in the config buffer). */ ++#define V4L2_PIX_FMT_RPI_BE v4l2_fourcc('R', 'P', 'B', 'P') ++ + /* SDR formats - used only for Software Defined Radio devices */ + #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ + #define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */ +@@ -822,6 +825,9 @@ struct v4l2_pix_format { + #define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 3A Parameters */ + #define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A Statistics */ + ++/* The metadata format identifier for our configuration buffers. */ ++#define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') ++ + /* priv field value to indicates that subsequent fields are valid. */ + #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe + diff --git a/target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch b/target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch new file mode 100644 index 0000000000..022a94af1c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch @@ -0,0 +1,386 @@ +From 89b748416358e4e04765b9a4f20e1c3d256b9d9e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 28 Jul 2021 11:13:39 +0100 +Subject: [PATCH] irqchip: irq-bcm2712-mip: Support for 2712's MIP + +irqchip: irq-bcm2712-mip: specify bitmap search size as ilog2(N) not N + +Freeing also has the same interface. + +irqchip: irq-bcm2712-mip: Fix build warnings + +Signed-off-by: Phil Elwell + +irqchip: bcm2712-mip: add a quick hack to optionally shift MSI vectors + +There are two MIP peripherals in bcm2712, the first gets a first-class +treatment where 64 consecutive GIC SPIs are assigned to all 64 output +vectors. The second gets an agglomeration of 17 GIC SPIs, but only 8 of +these are consecutive starting at the 8th output vector. + +For now, allow the use of this smaller contiguous range within a larger +whole. + +Signed-off-by: Jonathan Bell +--- + drivers/irqchip/Kconfig | 8 + + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-bcm2712-mip.c | 325 ++++++++++++++++++++++++++++++ + 3 files changed, 334 insertions(+) + create mode 100644 drivers/irqchip/irq-bcm2712-mip.c + +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -109,6 +109,14 @@ config I8259 + bool + select IRQ_DOMAIN + ++config BCM2712_MIP ++ bool "Broadcom 2712 MSI-X Interrupt Peripheral support" ++ depends on ARM_GIC ++ select GENERIC_IRQ_CHIP ++ select IRQ_DOMAIN ++ help ++ Enable support for the Broadcom BCM2712 MSI-X target peripheral. ++ + config BCM6345_L1_IRQ + bool + select GENERIC_IRQ_CHIP +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -63,6 +63,7 @@ obj-$(CONFIG_XTENSA_MX) += irq-xtensa- + obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o + obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o + obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o ++obj-$(CONFIG_BCM2712_MIP) += irq-bcm2712-mip.o + obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o + obj-$(CONFIG_BCM7038_L1_IRQ) += irq-bcm7038-l1.o + obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o +--- /dev/null ++++ b/drivers/irqchip/irq-bcm2712-mip.c +@@ -0,0 +1,325 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2021 Raspberry Pi Ltd., All Rights Reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define MIP_INT_RAISED 0x00 ++#define MIP_INT_CLEARED 0x10 ++#define MIP_INT_CFGL_HOST 0x20 ++#define MIP_INT_CFGH_HOST 0x30 ++#define MIP_INT_MASKL_HOST 0x40 ++#define MIP_INT_MASKH_HOST 0x50 ++#define MIP_INT_MASKL_VPU 0x60 ++#define MIP_INT_MASKH_VPU 0x70 ++#define MIP_INT_STATUSL_HOST 0x80 ++#define MIP_INT_STATUSH_HOST 0x90 ++#define MIP_INT_STATUSL_VPU 0xa0 ++#define MIP_INT_STATUSH_VPU 0xb0 ++ ++struct mip_priv { ++ spinlock_t msi_map_lock; ++ spinlock_t hw_lock; ++ void * __iomem base; ++ phys_addr_t msg_addr; ++ u32 msi_base; /* The SGI number that MSIs start */ ++ u32 num_msis; /* The number of SGIs for MSIs */ ++ u32 msi_offset; /* Shift the allocated msi up by N */ ++ unsigned long *msi_map; ++}; ++ ++static void mip_mask_msi_irq(struct irq_data *d) ++{ ++ pci_msi_mask_irq(d); ++ irq_chip_mask_parent(d); ++} ++ ++static void mip_unmask_msi_irq(struct irq_data *d) ++{ ++ pci_msi_unmask_irq(d); ++ irq_chip_unmask_parent(d); ++} ++ ++static void mip_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) ++{ ++ struct mip_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ msg->address_hi = upper_32_bits(priv->msg_addr); ++ msg->address_lo = lower_32_bits(priv->msg_addr); ++ msg->data = d->hwirq; ++} ++ ++// The "bus-specific" irq_chip (the MIP doesn't _have_ to be used with PCIe) ++ ++static struct irq_chip mip_msi_irq_chip = { ++ .name = "MIP-MSI", ++ .irq_unmask = mip_unmask_msi_irq, ++ .irq_mask = mip_mask_msi_irq, ++ .irq_eoi = irq_chip_eoi_parent, ++ .irq_set_affinity = irq_chip_set_affinity_parent, ++}; ++ ++static struct msi_domain_info mip_msi_domain_info = { ++ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | ++ MSI_FLAG_PCI_MSIX), ++ .chip = &mip_msi_irq_chip, ++}; ++ ++// The "middle" irq_chip (the hardware control part) ++ ++static struct irq_chip mip_irq_chip = { ++ .name = "MIP", ++ .irq_mask = irq_chip_mask_parent, ++ .irq_unmask = irq_chip_unmask_parent, ++ .irq_eoi = irq_chip_eoi_parent, ++ .irq_set_affinity = irq_chip_set_affinity_parent, ++ .irq_set_type = irq_chip_set_type_parent, ++ .irq_compose_msi_msg = mip_compose_msi_msg, ++}; ++ ++ ++// And a domain to connect it to its parent (the GIC) ++ ++static int mip_irq_domain_alloc(struct irq_domain *domain, ++ unsigned int virq, unsigned int nr_irqs, ++ void *args) ++{ ++ struct mip_priv *priv = domain->host_data; ++ struct irq_fwspec fwspec; ++ struct irq_data *irqd; ++ int hwirq, ret, i; ++ ++ spin_lock(&priv->msi_map_lock); ++ ++ hwirq = bitmap_find_free_region(priv->msi_map, priv->num_msis, ilog2(nr_irqs)); ++ ++ spin_unlock(&priv->msi_map_lock); ++ ++ if (hwirq < 0) ++ return -ENOSPC; ++ ++ hwirq += priv->msi_offset; ++ fwspec.fwnode = domain->parent->fwnode; ++ fwspec.param_count = 3; ++ fwspec.param[0] = 0; ++ fwspec.param[1] = hwirq + priv->msi_base; ++ fwspec.param[2] = IRQ_TYPE_EDGE_RISING; ++ ++ ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &fwspec); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < nr_irqs; i++) { ++ irqd = irq_domain_get_irq_data(domain->parent, virq + i); ++ irqd->chip->irq_set_type(irqd, IRQ_TYPE_EDGE_RISING); ++ ++ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, ++ &mip_irq_chip, priv); ++ irqd = irq_get_irq_data(virq + i); ++ irqd_set_single_target(irqd); ++ irqd_set_affinity_on_activate(irqd); ++ } ++ ++ return 0; ++} ++ ++static void mip_irq_domain_free(struct irq_domain *domain, ++ unsigned int virq, unsigned int nr_irqs) ++{ ++ struct irq_data *d = irq_domain_get_irq_data(domain, virq); ++ struct mip_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ irq_domain_free_irqs_parent(domain, virq, nr_irqs); ++ d->hwirq -= priv->msi_offset; ++ ++ spin_lock(&priv->msi_map_lock); ++ ++ bitmap_release_region(priv->msi_map, d->hwirq, ilog2(nr_irqs)); ++ ++ spin_unlock(&priv->msi_map_lock); ++} ++ ++#if 0 ++static int mip_irq_domain_activate(struct irq_domain *domain, ++ struct irq_data *d, bool reserve) ++{ ++ struct mip_priv *priv = irq_data_get_irq_chip_data(d); ++ unsigned long flags; ++ unsigned int irq = d->hwirq; ++ void *__iomem reg = priv->base + ++ ((irq < 32) ? MIP_INT_MASKL_HOST : MIP_INT_MASKH_HOST); ++ u32 val; ++ ++ spin_lock_irqsave(&priv->hw_lock, flags); ++ val = readl(reg); ++ val &= ~(1 << (irq % 32)); // Clear the mask ++ writel(val, reg); ++ spin_unlock_irqrestore(&priv->hw_lock, flags); ++ return 0; ++} ++ ++static void mip_irq_domain_deactivate(struct irq_domain *domain, ++ struct irq_data *d) ++{ ++ struct mip_priv *priv = irq_data_get_irq_chip_data(d); ++ unsigned long flags; ++ unsigned int irq = d->hwirq - priv->msi_base; ++ void *__iomem reg = priv->base + ++ ((irq < 32) ? MIP_INT_MASKL_HOST : MIP_INT_MASKH_HOST); ++ u32 val; ++ ++ spin_lock_irqsave(&priv->hw_lock, flags); ++ val = readl(reg); ++ val |= (1 << (irq % 32)); // Mask it out ++ writel(val, reg); ++ spin_unlock_irqrestore(&priv->hw_lock, flags); ++} ++#endif ++ ++static const struct irq_domain_ops mip_irq_domain_ops = { ++ .alloc = mip_irq_domain_alloc, ++ .free = mip_irq_domain_free, ++ //.activate = mip_irq_domain_activate, ++ //.deactivate = mip_irq_domain_deactivate, ++}; ++ ++static int mip_init_domains(struct mip_priv *priv, ++ struct device_node *node) ++{ ++ struct irq_domain *middle_domain, *msi_domain, *gic_domain; ++ struct device_node *gic_node; ++ ++ gic_node = of_irq_find_parent(node); ++ if (!gic_node) { ++ pr_err("Failed to find the GIC node\n"); ++ return -ENODEV; ++ } ++ ++ gic_domain = irq_find_host(gic_node); ++ if (!gic_domain) { ++ pr_err("Failed to find the GIC domain\n"); ++ return -ENXIO; ++ } ++ ++ middle_domain = irq_domain_add_tree(NULL, ++ &mip_irq_domain_ops, ++ priv); ++ if (!middle_domain) { ++ pr_err("Failed to create the MIP middle domain\n"); ++ return -ENOMEM; ++ } ++ ++ middle_domain->parent = gic_domain; ++ ++ msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), ++ &mip_msi_domain_info, ++ middle_domain); ++ if (!msi_domain) { ++ pr_err("Failed to create MSI domain\n"); ++ irq_domain_remove(middle_domain); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static int __init mip_of_msi_init(struct device_node *node, ++ struct device_node *parent) ++{ ++ struct mip_priv *priv; ++ struct resource res; ++ int ret; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ spin_lock_init(&priv->msi_map_lock); ++ spin_lock_init(&priv->hw_lock); ++ ++ ret = of_address_to_resource(node, 0, &res); ++ if (ret) { ++ pr_err("Failed to allocate resource\n"); ++ goto err_priv; ++ } ++ ++ if (of_property_read_u32(node, "brcm,msi-base-spi", &priv->msi_base)) { ++ pr_err("Unable to parse MSI base\n"); ++ ret = -EINVAL; ++ goto err_priv; ++ } ++ ++ if (of_property_read_u32(node, "brcm,msi-num-spis", &priv->num_msis)) { ++ pr_err("Unable to parse MSI numbers\n"); ++ ret = -EINVAL; ++ goto err_priv; ++ } ++ ++ if (of_property_read_u32(node, "brcm,msi-offset", &priv->msi_offset)) ++ priv->msi_offset = 0; ++ ++ if (of_property_read_u64(node, "brcm,msi-pci-addr", &priv->msg_addr)) { ++ pr_err("Unable to parse MSI address\n"); ++ ret = -EINVAL; ++ goto err_priv; ++ } ++ ++ priv->base = ioremap(res.start, resource_size(&res)); ++ if (!priv->base) { ++ pr_err("Failed to ioremap regs\n"); ++ ret = -ENOMEM; ++ goto err_priv; ++ } ++ ++ priv->msi_map = kcalloc(BITS_TO_LONGS(priv->num_msis), ++ sizeof(*priv->msi_map), ++ GFP_KERNEL); ++ if (!priv->msi_map) { ++ ret = -ENOMEM; ++ goto err_base; ++ } ++ ++ pr_debug("Registering %d msixs, starting at %d\n", ++ priv->num_msis, priv->msi_base); ++ ++ /* ++ * Begin with all MSI-Xs masked in for the host, masked out for the ++ * VPU, and edge-triggered. ++ */ ++ writel(0, priv->base + MIP_INT_MASKL_HOST); ++ writel(0, priv->base + MIP_INT_MASKH_HOST); ++ writel(~0, priv->base + MIP_INT_MASKL_VPU); ++ writel(~0, priv->base + MIP_INT_MASKH_VPU); ++ writel(~0, priv->base + MIP_INT_CFGL_HOST); ++ writel(~0, priv->base + MIP_INT_CFGH_HOST); ++ ++ ret = mip_init_domains(priv, node); ++ if (ret) { ++ pr_err("Failed to allocate msi_map\n"); ++ goto err_map; ++ } ++ ++ return 0; ++ ++err_map: ++ kfree(priv->msi_map); ++ ++err_base: ++ iounmap(priv->base); ++ ++err_priv: ++ kfree(priv); ++ ++ pr_err("%s: failed - err %d\n", __func__, ret); ++ ++ return ret; ++} ++IRQCHIP_DECLARE(bcm_mip, "brcm,bcm2712-mip-intc", mip_of_msi_init); diff --git a/target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch b/target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch new file mode 100644 index 0000000000..a4328e5bc7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch @@ -0,0 +1,47 @@ +From 87b1126181f79fb2558652af0d7fafd9deaab5f3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 7 Sep 2021 14:49:00 +0100 +Subject: [PATCH] reset: reset-brcmstb-rescal: Support shared use + +reset_control_reset should not be used with shared reset controllers. +Add support for reset_control_assert and _deassert to get the desired +behaviour and avoid ugly warnings in the kernel log. + +Signed-off-by: Phil Elwell +--- + drivers/reset/reset-brcmstb-rescal.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/reset/reset-brcmstb-rescal.c ++++ b/drivers/reset/reset-brcmstb-rescal.c +@@ -20,6 +20,7 @@ struct brcm_rescal_reset { + struct reset_controller_dev rcdev; + }; + ++/* Also doubles a deassert */ + static int brcm_rescal_reset_set(struct reset_controller_dev *rcdev, + unsigned long id) + { +@@ -52,6 +53,13 @@ static int brcm_rescal_reset_set(struct + return 0; + } + ++/* A dummy function - deassert/reset does all the work */ ++static int brcm_rescal_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ return 0; ++} ++ + static int brcm_rescal_reset_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) + { +@@ -61,6 +69,8 @@ static int brcm_rescal_reset_xlate(struc + + static const struct reset_control_ops brcm_rescal_reset_ops = { + .reset = brcm_rescal_reset_set, ++ .deassert = brcm_rescal_reset_set, ++ .assert = brcm_rescal_reset_assert, + }; + + static int brcm_rescal_reset_probe(struct platform_device *pdev) diff --git a/target/linux/bcm27xx/patches-6.1/950-0864-net-macb-Also-set-DMA-coherent-mask.patch b/target/linux/bcm27xx/patches-6.1/950-0864-net-macb-Also-set-DMA-coherent-mask.patch new file mode 100644 index 0000000000..88d92fbb20 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0864-net-macb-Also-set-DMA-coherent-mask.patch @@ -0,0 +1,418 @@ +From bd36586dd9e05bde8e23dc3d99771269b48b65f8 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 10 Sep 2021 17:20:45 +0100 +Subject: [PATCH] net: macb: Also set DMA coherent mask + +macb: Add device tree properties that allow configuration of the AXI max pipeline register + +net: macb: add support for ethtool interrupt moderation configuration + +Only global throttling of rx or tx by time quanta is supported. + +Signed-off-by: Jonathan Bell + +macb: add platform device shutdown function. Prevents AXI master over PCIE from hanging when the host is rebooted. + +net: macb: increase polling interval for MDIO completion + +MDIO is a slow bus (single-digit MHz). Polling at 1us intervals +is a bit aggressive, so increase to 100us as the transaction +usually takes 100-200us to complete. + +Signed-off-by: Jonathan Bell + +net: macb: Several patches for RP1 + +64-bit RX fix + +Also set DMA coherent mask + +Add device tree properties that allow configuration of the AXI max +pipeline register + +Add support for ethtool interrupt moderation configuration + +Only global throttling of rx or tx by time quanta is supported. + +Add platform device shutdown function. Prevents AXI master over PCIE +from hanging when the host is rebooted. + +Increase polling interval for MDIO completion + +MDIO is a slow bus (single-digit MHz). Polling at 1us intervals +is a bit aggressive, so increase to 100us as the transaction +usually takes 100-200us to complete. + +Signed-off-by: Jonathan Bell + +net: macb: Support the phy-reset-gpios property + +Allow a PHY to be reset with an optional GPIO. The reset duration can +be specified in milliseconds - the default is 10ms. + +Signed-off-by: Phil Elwell + +drivers: net: macb: close device on driver shutdown + +Fix some suspicious locking and instead call into macb_close, which +deregisters and frees all resources the corresponding macb_open +claimed. + +Signed-off-by: Jonathan Bell + +net: macb: add hack to prevent TX stalls in a quiet system + +See https://github.com/raspberrypi/linux-2712/issues/89 + +There is some critical window during TX where a further write to the +TSTART bit while TX is active does not cause newly queued TX descriptors +to be consumed. + +For now "wait a bit, then try anyway" seems to work. + +Requires further investigation, but this unsticks NFS reliably. + +Signed-off-by: Jonathan Bell + +net: macb: set default interrupt moderation for GEM hardware + +Defaulting to intmod = 0 is antisocial, as the MAC can generate over +130,000 interrupts per second. 50us is a sensible default. + +Signed-off-by: Jonathan Bell +--- + drivers/net/ethernet/cadence/macb.h | 25 ++++ + drivers/net/ethernet/cadence/macb_main.c | 151 ++++++++++++++++++++++- + 2 files changed, 174 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/cadence/macb.h ++++ b/drivers/net/ethernet/cadence/macb.h +@@ -84,6 +84,8 @@ + #define GEM_DMACFG 0x0010 /* DMA Configuration */ + #define GEM_JML 0x0048 /* Jumbo Max Length */ + #define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */ ++#define GEM_AMP 0x0054 /* AXI Max Pipeline */ ++#define GEM_INTMOD 0x005c /* Interrupt moderation */ + #define GEM_HRB 0x0080 /* Hash Bottom */ + #define GEM_HRT 0x0084 /* Hash Top */ + #define GEM_SA1B 0x0088 /* Specific1 Bottom */ +@@ -346,6 +348,21 @@ + #define GEM_ADDR64_OFFSET 30 /* Address bus width - 64b or 32b */ + #define GEM_ADDR64_SIZE 1 + ++/* Bitfields in AMP */ ++#define GEM_AR2R_MAX_PIPE_OFFSET 0 /* Maximum number of outstanding AXI read requests */ ++#define GEM_AR2R_MAX_PIPE_SIZE 8 ++#define GEM_AW2W_MAX_PIPE_OFFSET 8 /* Maximum number of outstanding AXI write requests */ ++#define GEM_AW2W_MAX_PIPE_SIZE 8 ++#define GEM_AW2B_FILL_OFFSET 16 /* Select wether the max AW2W transactions operates between: */ ++#define GEM_AW2B_FILL_AW2W 0 /* 0: the AW to W AXI channel */ ++#define GEM_AW2B_FILL_AW2B 1 /* 1: AW to B channel */ ++#define GEM_AW2B_FILL_SIZE 1 ++ ++/* Bitfields in INTMOD */ ++#define GEM_RX_MODERATION_OFFSET 0 /* RX interrupt moderation */ ++#define GEM_RX_MODERATION_SIZE 8 ++#define GEM_TX_MODERATION_OFFSET 16 /* TX interrupt moderation */ ++#define GEM_TX_MODERATION_SIZE 8 + + /* Bitfields in NSR */ + #define MACB_NSR_LINK_OFFSET 0 /* pcs_link_state */ +@@ -798,6 +815,7 @@ + }) + + #define MACB_READ_NSR(bp) macb_readl(bp, NSR) ++#define MACB_READ_TSR(bp) macb_readl(bp, TSR) + + /* struct macb_dma_desc - Hardware DMA descriptor + * @addr: DMA address of data buffer +@@ -1217,6 +1235,7 @@ struct macb_queue { + dma_addr_t tx_ring_dma; + struct work_struct tx_error_task; + bool txubr_pending; ++ bool tx_pending; + struct napi_struct napi_tx; + + dma_addr_t rx_ring_dma; +@@ -1286,9 +1305,15 @@ struct macb { + + u32 caps; + unsigned int dma_burst_length; ++ u8 aw2w_max_pipe; ++ u8 ar2r_max_pipe; ++ bool use_aw2b_fill; + + phy_interface_t phy_interface; + ++ struct gpio_desc *phy_reset_gpio; ++ int phy_reset_ms; ++ + /* AT91RM9200 transmit queue (1 on wire + 1 queued) */ + struct macb_tx_skb rm9200_txq[2]; + unsigned int max_tx_length; +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -41,6 +41,9 @@ + #include + #include "macb.h" + ++static unsigned int txdelay = 35; ++module_param(txdelay, uint, 0644); ++ + /* This structure is only used for MACB on SiFive FU540 devices */ + struct sifive_fu540_macb_mgmt { + void __iomem *reg; +@@ -336,7 +339,7 @@ static int macb_mdio_wait_for_idle(struc + u32 val; + + return readx_poll_timeout(MACB_READ_NSR, bp, val, val & MACB_BIT(IDLE), +- 1, MACB_MDIO_TIMEOUT); ++ 100, MACB_MDIO_TIMEOUT); + } + + static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +@@ -442,6 +445,19 @@ mdio_pm_exit: + return status; + } + ++static int macb_mdio_reset(struct mii_bus *bus) ++{ ++ struct macb *bp = bus->priv; ++ ++ if (bp->phy_reset_gpio) { ++ gpiod_set_value_cansleep(bp->phy_reset_gpio, 1); ++ msleep(bp->phy_reset_ms); ++ gpiod_set_value_cansleep(bp->phy_reset_gpio, 0); ++ } ++ ++ return 0; ++} ++ + static void macb_init_buffers(struct macb *bp) + { + struct macb_queue *queue; +@@ -915,6 +931,7 @@ static int macb_mii_init(struct macb *bp + bp->mii_bus->name = "MACB_mii_bus"; + bp->mii_bus->read = &macb_mdio_read; + bp->mii_bus->write = &macb_mdio_write; ++ bp->mii_bus->reset = &macb_mdio_reset; + snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + bp->pdev->name, bp->pdev->id); + bp->mii_bus->priv = bp; +@@ -1584,6 +1601,11 @@ static int macb_rx(struct macb_queue *qu + + macb_init_rx_ring(queue); + queue_writel(queue, RBQP, queue->rx_ring_dma); ++#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT ++ if (bp->hw_dma_cap & HW_DMA_CAP_64B) ++ macb_writel(bp, RBQPH, ++ upper_32_bits(queue->rx_ring_dma)); ++#endif + + macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); + +@@ -1884,8 +1906,9 @@ static irqreturn_t macb_interrupt(int ir + queue_writel(queue, ISR, MACB_BIT(TCOMP) | + MACB_BIT(TXUBR)); + +- if (status & MACB_BIT(TXUBR)) { ++ if (status & MACB_BIT(TXUBR) || queue->tx_pending) { + queue->txubr_pending = true; ++ queue->tx_pending = 0; + wmb(); // ensure softirq can see update + } + +@@ -2332,6 +2355,11 @@ static netdev_tx_t macb_start_xmit(struc + skb_tx_timestamp(skb); + + spin_lock_irq(&bp->lock); ++ ++ /* TSTART write might get dropped, so make the IRQ retrigger a buffer read */ ++ if (macb_readl(bp, TSR) & MACB_BIT(TGO)) ++ queue->tx_pending = 1; ++ + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); + spin_unlock_irq(&bp->lock); + +@@ -2699,6 +2727,37 @@ static void macb_configure_dma(struct ma + } + } + ++static void gem_init_axi(struct macb *bp) ++{ ++ u32 amp; ++ ++ /* AXI pipeline setup - don't touch values unless specified in device ++ * tree. Some hardware could have reset values > 1. ++ */ ++ amp = gem_readl(bp, AMP); ++ ++ if (bp->use_aw2b_fill) ++ amp = GEM_BFINS(AW2B_FILL, bp->use_aw2b_fill, amp); ++ if (bp->aw2w_max_pipe) ++ amp = GEM_BFINS(AW2W_MAX_PIPE, bp->aw2w_max_pipe, amp); ++ if (bp->ar2r_max_pipe) ++ amp = GEM_BFINS(AR2R_MAX_PIPE, bp->ar2r_max_pipe, amp); ++ ++ gem_writel(bp, AMP, amp); ++} ++ ++static void gem_init_intmod(struct macb *bp) ++{ ++ unsigned int throttle; ++ u32 intmod = 0; ++ ++ /* Use sensible interrupt moderation thresholds (50us rx and tx) */ ++ throttle = (1000 * 50) / 800; ++ intmod = GEM_BFINS(TX_MODERATION, throttle, intmod); ++ intmod = GEM_BFINS(RX_MODERATION, throttle, intmod); ++ gem_writel(bp, INTMOD, intmod); ++} ++ + static void macb_init_hw(struct macb *bp) + { + u32 config; +@@ -2727,6 +2786,11 @@ static void macb_init_hw(struct macb *bp + if (bp->caps & MACB_CAPS_JUMBO) + bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK; + ++ if (macb_is_gem(bp)) { ++ gem_init_axi(bp); ++ gem_init_intmod(bp); ++ } ++ + macb_configure_dma(bp); + } + +@@ -3072,6 +3136,52 @@ static void gem_get_ethtool_strings(stru + } + } + ++static int gem_set_coalesce(struct net_device *dev, ++ struct ethtool_coalesce *ec, ++ struct kernel_ethtool_coalesce *kernel_coal, ++ struct netlink_ext_ack *extack) ++{ ++ struct macb *bp = netdev_priv(dev); ++ unsigned int tx_throttle; ++ unsigned int rx_throttle; ++ u32 intmod = 0; ++ ++ /* GEM has simple IRQ throttling support. RX and TX interrupts ++ * are separately moderated on 800ns quantums, with no support ++ * for frame coalescing. ++ */ ++ ++ /* Max is 255 * 0.8us = 204us. Zero implies no moderation. */ ++ if (ec->rx_coalesce_usecs > 204 || ec->tx_coalesce_usecs > 204) ++ return -EINVAL; ++ ++ tx_throttle = (1000 * ec->tx_coalesce_usecs) / 800; ++ rx_throttle = (1000 * ec->rx_coalesce_usecs) / 800; ++ ++ intmod = GEM_BFINS(TX_MODERATION, tx_throttle, intmod); ++ intmod = GEM_BFINS(RX_MODERATION, rx_throttle, intmod); ++ ++ gem_writel(bp, INTMOD, intmod); ++ ++ return 0; ++} ++ ++static int gem_get_coalesce(struct net_device *dev, ++ struct ethtool_coalesce *ec, ++ struct kernel_ethtool_coalesce *kernel_coal, ++ struct netlink_ext_ack *extack) ++{ ++ struct macb *bp = netdev_priv(dev); ++ u32 intmod; ++ ++ intmod = gem_readl(bp, INTMOD); ++ ++ ec->tx_coalesce_usecs = (GEM_BFEXT(TX_MODERATION, intmod) * 800) / 1000; ++ ec->rx_coalesce_usecs = (GEM_BFEXT(RX_MODERATION, intmod) * 800) / 1000; ++ ++ return 0; ++} ++ + static struct net_device_stats *macb_get_stats(struct net_device *dev) + { + struct macb *bp = netdev_priv(dev); +@@ -3664,6 +3774,8 @@ static const struct ethtool_ops macb_eth + }; + + static const struct ethtool_ops gem_ethtool_ops = { ++ .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | ++ ETHTOOL_COALESCE_TX_USECS, + .get_regs_len = macb_get_regs_len, + .get_regs = macb_get_regs, + .get_wol = macb_get_wol, +@@ -3673,6 +3785,8 @@ static const struct ethtool_ops gem_etht + .get_ethtool_stats = gem_get_ethtool_stats, + .get_strings = gem_get_ethtool_strings, + .get_sset_count = gem_get_sset_count, ++ .get_coalesce = gem_get_coalesce, ++ .set_coalesce = gem_set_coalesce, + .get_link_ksettings = macb_get_link_ksettings, + .set_link_ksettings = macb_set_link_ksettings, + .get_ringparam = macb_get_ringparam, +@@ -4940,6 +5054,10 @@ static int macb_probe(struct platform_de + + bp->usrio = macb_config->usrio; + ++ device_property_read_u8(&pdev->dev, "cdns,aw2w-max-pipe", &bp->aw2w_max_pipe); ++ device_property_read_u8(&pdev->dev, "cdns,ar2r-max-pipe", &bp->ar2r_max_pipe); ++ bp->use_aw2b_fill = device_property_read_bool(&pdev->dev, "cdns,use-aw2b-fill"); ++ + spin_lock_init(&bp->lock); + + /* setup capabilities */ +@@ -4995,6 +5113,21 @@ static int macb_probe(struct platform_de + else + bp->phy_interface = interface; + ++ /* optional PHY reset-related properties */ ++ bp->phy_reset_gpio = devm_gpiod_get_optional(&pdev->dev, "phy-reset", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(bp->phy_reset_gpio)) { ++ dev_err(&pdev->dev, "Failed to obtain phy-reset gpio\n"); ++ err = PTR_ERR(bp->phy_reset_gpio); ++ goto err_out_free_netdev; ++ } ++ ++ bp->phy_reset_ms = 10; ++ of_property_read_u32(np, "phy-reset-duration", &bp->phy_reset_ms); ++ /* A sane reset duration should not be longer than 1s */ ++ if (bp->phy_reset_ms > 1000) ++ bp->phy_reset_ms = 1000; ++ + /* IP specific init */ + err = init(pdev); + if (err) +@@ -5071,6 +5204,19 @@ static int macb_remove(struct platform_d + return 0; + } + ++static void macb_shutdown(struct platform_device *pdev) ++{ ++ struct net_device *dev; ++ ++ dev = platform_get_drvdata(pdev); ++ ++ rtnl_lock(); ++ netif_device_detach(dev); ++ if (netif_running(dev)) ++ dev_close(dev); ++ rtnl_unlock(); ++} ++ + static int __maybe_unused macb_suspend(struct device *dev) + { + struct net_device *netdev = dev_get_drvdata(dev); +@@ -5285,6 +5431,7 @@ static const struct dev_pm_ops macb_pm_o + static struct platform_driver macb_driver = { + .probe = macb_probe, + .remove = macb_remove, ++ .shutdown = macb_shutdown, + .driver = { + .name = "macb", + .of_match_table = of_match_ptr(macb_dt_ids), diff --git a/target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch b/target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch new file mode 100644 index 0000000000..f6944e226f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch @@ -0,0 +1,384 @@ +From 4ffa5f2c5fc7854683964bb2f2bf23907c18213f Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 13 Sep 2021 11:14:32 +0100 +Subject: [PATCH] usb: dwc3: Set DMA and coherent masks early + +dwc3 allocates scratch and event buffers in the top-level driver. Hack the +probe function to set the DMA mask before trying to allocate these. + +I think the event buffers are only used in device mode, but the scratch +buffers may be used if core hibernation is enabled. + +usb: dwc3: add support for new DT quirks + +Apply the optional axi-pipe-limit and dis-in-autoretry-quirk properties +during driver probe. + +Signed-off-by: Jonathan Bell + +phy: phy-brcm-usb: Add 2712 support + +usb: dwc3: if the host controller instance number is present in DT, use it + +If two instances of a dwc3 host controller are specified in devicetree, +then the probe order may be arbitrary which results in the device names +swapping on a per-boot basis. + +If a "usb" alias with the instance number is specified, then use +that to construct the device name instead of autogenerating one. + +Signed-off-by: Jonathan Bell + +rp1 dwc3 changes + +drivers: usb: dwc3: allow setting GTXTHRCFG on dwc_usb3.0 hardware + +Equivalent register fields exist in the SuperSpeed Host version of the +hardware, so allow the use of TX thresholds if specified in devicetree. + +Signed-off-by: Jonathan Bell + +drivers: usb: dwc3: remove downstream quirk dis-in-autoretry + +Upstream have unilaterally disabled the feature. + +Partially reverts 6e9142a26ee0fdc3a5adc49ed6cedc0b16ec2ed1 (downstream) + +Signed-off-by: Jonathan Bell +--- + drivers/phy/broadcom/Kconfig | 2 +- + .../phy/broadcom/phy-brcm-usb-init-synopsys.c | 59 +++++++++++++++++++ + drivers/phy/broadcom/phy-brcm-usb-init.h | 2 + + drivers/phy/broadcom/phy-brcm-usb.c | 18 +++++- + drivers/usb/dwc3/core.c | 52 ++++++++++++++++ + drivers/usb/dwc3/core.h | 10 ++++ + drivers/usb/dwc3/host.c | 17 ++++-- + 7 files changed, 153 insertions(+), 7 deletions(-) + +--- a/drivers/phy/broadcom/Kconfig ++++ b/drivers/phy/broadcom/Kconfig +@@ -93,7 +93,7 @@ config PHY_BRCM_SATA + + config PHY_BRCM_USB + tristate "Broadcom STB USB PHY driver" +- depends on ARCH_BCMBCA || ARCH_BRCMSTB || COMPILE_TEST ++ depends on ARCH_BCMBCA || ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST + depends on OF + select GENERIC_PHY + select SOC_BRCMSTB if ARCH_BRCMSTB +--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c ++++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c +@@ -318,6 +318,36 @@ static void usb_init_common_7216(struct + usb_init_common(params); + } + ++static void usb_init_common_2712(struct brcm_usb_init_params *params) ++{ ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; ++ void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC]; ++ u32 reg; ++ ++ if (params->syscon_piarbctl) ++ syscon_piarbctl_init(params->syscon_piarbctl); ++ ++ USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN); ++ ++ usb_wake_enable_7211b0(params, false); ++ ++ usb_init_common(params); ++ ++ /* ++ * The BDC controller will get occasional failures with ++ * the default "Read Transaction Size" of 6 (1024 bytes). ++ * Set it to 4 (256 bytes). ++ */ ++ if ((params->mode != USB_CTLR_MODE_HOST) && bdc_ec) { ++ reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA); ++ reg &= ~BDC_EC_AXIRDA_RTS_MASK; ++ reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT); ++ brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA); ++ } ++ ++ usb2_eye_fix_7211b0(params); ++} ++ + static void usb_init_xhci(struct brcm_usb_init_params *params) + { + pr_debug("%s\n", __func__); +@@ -363,6 +393,18 @@ static void usb_uninit_common_7211b0(str + + } + ++static void usb_uninit_common_2712(struct brcm_usb_init_params *params) ++{ ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; ++ ++ if (params->wake_enabled) { ++ USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN); ++ usb_wake_enable_7211b0(params, true); ++ } else { ++ USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN); ++ } ++} ++ + static void usb_uninit_xhci(struct brcm_usb_init_params *params) + { + +@@ -417,6 +459,16 @@ static const struct brcm_usb_init_ops bc + .set_dual_select = usb_set_dual_select, + }; + ++static const struct brcm_usb_init_ops bcm2712_ops = { ++ .init_ipp = usb_init_ipp, ++ .init_common = usb_init_common_2712, ++ .init_xhci = usb_init_xhci, ++ .uninit_common = usb_uninit_common_2712, ++ .uninit_xhci = usb_uninit_xhci, ++ .get_dual_select = usb_get_dual_select, ++ .set_dual_select = usb_set_dual_select, ++}; ++ + void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params) + { + +@@ -434,3 +486,10 @@ void brcm_usb_dvr_init_7211b0(struct brc + params->family_name = "7211"; + params->ops = &bcm7211b0_ops; + } ++ ++void brcm_usb_dvr_init_2712(struct brcm_usb_init_params *params) ++{ ++ params->family_name = "2712"; ++ params->ops = &bcm2712_ops; ++ params->suspend_with_clocks = true; ++} +--- a/drivers/phy/broadcom/phy-brcm-usb-init.h ++++ b/drivers/phy/broadcom/phy-brcm-usb-init.h +@@ -61,12 +61,14 @@ struct brcm_usb_init_params { + const struct brcm_usb_init_ops *ops; + struct regmap *syscon_piarbctl; + bool wake_enabled; ++ bool suspend_with_clocks; + }; + + void brcm_usb_dvr_init_4908(struct brcm_usb_init_params *params); + void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params); + void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params); + void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params); ++void brcm_usb_dvr_init_2712(struct brcm_usb_init_params *params); + + static inline u32 brcm_usb_readl(void __iomem *addr) + { +--- a/drivers/phy/broadcom/phy-brcm-usb.c ++++ b/drivers/phy/broadcom/phy-brcm-usb.c +@@ -76,7 +76,7 @@ struct brcm_usb_phy_data { + }; + + static s8 *node_reg_names[BRCM_REGS_MAX] = { +- "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec" ++ "ctrl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec" + }; + + static int brcm_pm_notifier(struct notifier_block *notifier, +@@ -315,6 +315,18 @@ static const struct match_chip_info chip + .optional_reg = BRCM_REGS_BDC_EC, + }; + ++static const struct match_chip_info chip_info_2712 = { ++ .init_func = &brcm_usb_dvr_init_2712, ++ .required_regs = { ++ BRCM_REGS_CTRL, ++ BRCM_REGS_XHCI_EC, ++ BRCM_REGS_XHCI_GBL, ++ BRCM_REGS_USB_MDIO, ++ -1, ++ }, ++ .optional_reg = BRCM_REGS_BDC_EC, ++}; ++ + static const struct match_chip_info chip_info_7445 = { + .init_func = &brcm_usb_dvr_init_7445, + .required_regs = { +@@ -338,6 +350,10 @@ static const struct of_device_id brcm_us + .data = &chip_info_7211b0, + }, + { ++ .compatible = "brcm,bcm2712-usb-phy", ++ .data = &chip_info_2712, ++ }, ++ { + .compatible = "brcm,brcmstb-usb-phy", + .data = &chip_info_7445, + }, +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1216,6 +1216,24 @@ static void dwc3_config_threshold(struct + } + } + ++static void dwc3_set_axi_pipe_limit(struct dwc3 *dwc) ++{ ++ struct device *dev = dwc->dev; ++ u32 cfg; ++ ++ if (!dwc->axi_pipe_limit) ++ return; ++ if (dwc->axi_pipe_limit > 16) { ++ dev_err(dev, "Invalid axi_pipe_limit property\n"); ++ return; ++ } ++ cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG1); ++ cfg &= ~DWC3_GSBUSCFG1_PIPETRANSLIMIT(15); ++ cfg |= DWC3_GSBUSCFG1_PIPETRANSLIMIT(dwc->axi_pipe_limit - 1); ++ ++ dwc3_writel(dwc->regs, DWC3_GSBUSCFG1, cfg); ++} ++ + /** + * dwc3_core_init - Low-level initialization of DWC3 Core + * @dwc: Pointer to our controller context structure +@@ -1308,6 +1326,8 @@ static int dwc3_core_init(struct dwc3 *d + + dwc3_set_incr_burst_type(dwc); + ++ dwc3_set_axi_pipe_limit(dwc); ++ + usb_phy_set_suspend(dwc->usb2_phy, 0); + usb_phy_set_suspend(dwc->usb3_phy, 0); + ret = phy_power_on(dwc->usb2_generic_phy); +@@ -1541,6 +1561,7 @@ static void dwc3_get_properties(struct d + u8 tx_thr_num_pkt_prd = 0; + u8 tx_max_burst_prd = 0; + u8 tx_fifo_resize_max_num; ++ u8 axi_pipe_limit; + const char *usb_psy_name; + int ret; + +@@ -1563,6 +1584,9 @@ static void dwc3_get_properties(struct d + */ + tx_fifo_resize_max_num = 6; + ++ /* Default to 0 (don't override hardware defaults) */ ++ axi_pipe_limit = 0; ++ + dwc->maximum_speed = usb_get_maximum_speed(dev); + dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev); + dwc->dr_mode = usb_get_dr_mode(dev); +@@ -1678,6 +1702,9 @@ static void dwc3_get_properties(struct d + dwc->dis_split_quirk = device_property_read_bool(dev, + "snps,dis-split-quirk"); + ++ device_property_read_u8(dev, "snps,axi-pipe-limit", ++ &axi_pipe_limit); ++ + dwc->lpm_nyet_threshold = lpm_nyet_threshold; + dwc->tx_de_emphasis = tx_de_emphasis; + +@@ -1695,6 +1722,8 @@ static void dwc3_get_properties(struct d + dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd; + dwc->tx_max_burst_prd = tx_max_burst_prd; + ++ dwc->axi_pipe_limit = axi_pipe_limit; ++ + dwc->imod_interval = 0; + + dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num; +@@ -1903,6 +1932,12 @@ static int dwc3_probe(struct platform_de + + dwc3_get_properties(dwc); + ++ if (!dwc->sysdev_is_parent) { ++ ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); ++ if (ret) ++ return ret; ++ } ++ + dwc->reset = devm_reset_control_array_get_optional_shared(dev); + if (IS_ERR(dwc->reset)) { + ret = PTR_ERR(dwc->reset); +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -183,6 +183,9 @@ + #define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */ + #define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff + ++/* Global SoC Bus Configuration Register 1 */ ++#define DWC3_GSBUSCFG1_PIPETRANSLIMIT(n) (((n) & 0xf) << 8) ++ + /* Global Debug LSP MUX Select */ + #define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */ + #define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff) +@@ -1056,6 +1059,7 @@ struct dwc3_scratchpad_array { + * @tx_max_burst_prd: max periodic ESS transmit burst size + * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize + * @clear_stall_protocol: endpoint number that requires a delayed status phase ++ * @axi_max_pipe: set to override the maximum number of pipelined AXI transfers + * @hsphy_interface: "utmi" or "ulpi" + * @connected: true when we're connected to a host, false otherwise + * @softconnect: true when gadget connect is called, false when disconnect runs +@@ -1287,6 +1291,7 @@ struct dwc3 { + u8 tx_max_burst_prd; + u8 tx_fifo_resize_max_num; + u8 clear_stall_protocol; ++ u8 axi_pipe_limit; + + const char *hsphy_interface; + +--- a/drivers/usb/dwc3/host.c ++++ b/drivers/usb/dwc3/host.c +@@ -30,10 +30,10 @@ static void dwc3_host_fill_xhci_irq_res( + + static int dwc3_host_get_irq(struct dwc3 *dwc) + { +- struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); ++ struct platform_device *pdev = to_platform_device(dwc->dev); + int irq; + +- irq = platform_get_irq_byname_optional(dwc3_pdev, "host"); ++ irq = platform_get_irq_byname_optional(pdev, "host"); + if (irq > 0) { + dwc3_host_fill_xhci_irq_res(dwc, irq, "host"); + goto out; +@@ -42,7 +42,7 @@ static int dwc3_host_get_irq(struct dwc3 + if (irq == -EPROBE_DEFER) + goto out; + +- irq = platform_get_irq_byname_optional(dwc3_pdev, "dwc_usb3"); ++ irq = platform_get_irq_byname_optional(pdev, "dwc_usb3"); + if (irq > 0) { + dwc3_host_fill_xhci_irq_res(dwc, irq, "dwc_usb3"); + goto out; +@@ -51,7 +51,7 @@ static int dwc3_host_get_irq(struct dwc3 + if (irq == -EPROBE_DEFER) + goto out; + +- irq = platform_get_irq(dwc3_pdev, 0); ++ irq = platform_get_irq(pdev, 0); + if (irq > 0) { + dwc3_host_fill_xhci_irq_res(dwc, irq, NULL); + goto out; +@@ -66,16 +66,23 @@ out: + + int dwc3_host_init(struct dwc3 *dwc) + { ++ struct platform_device *pdev = to_platform_device(dwc->dev); + struct property_entry props[4]; + struct platform_device *xhci; + int ret, irq; + int prop_idx = 0; ++ int id; + + irq = dwc3_host_get_irq(dwc); + if (irq < 0) + return irq; + +- xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); ++ id = of_alias_get_id(pdev->dev.of_node, "usb"); ++ if (id >= 0) ++ xhci = platform_device_alloc("xhci-hcd", id); ++ else ++ xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); ++ + if (!xhci) { + dev_err(dwc->dev, "couldn't allocate xHCI device\n"); + return -ENOMEM; diff --git a/target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch b/target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch new file mode 100644 index 0000000000..a6f0c1961c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch @@ -0,0 +1,37 @@ +From 480c8e9f48f8a96c457eb3dc0079a73598fb7477 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 1 Dec 2021 19:43:08 +0000 +Subject: [PATCH] drm/panel/raspberrypi-touchscreen: Insert more delays. + +This avoids failures in cases where the panel is enabled +or re-probed very soon after being disabled or probed. +These can occur because the Atmel device can mis-behave +over I2C for a few ms after any write to the POWERON register. +--- + drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c ++++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +@@ -299,6 +299,13 @@ static int rpi_touchscreen_prepare(struc + struct rpi_touchscreen *ts = panel_to_ts(panel); + int i, data; + ++ /* ++ * Power up the Toshiba bridge. The Atmel device can misbehave ++ * over I2C for a few ms after writes to REG_POWERON (including the ++ * write in rpi_touchscreen_disable()), so sleep before and after. ++ * Also to ensure that the bridge has been off for at least 100ms. ++ */ ++ msleep(100); + rpi_touchscreen_i2c_write(ts, REG_POWERON, 1); + usleep_range(20000, 25000); + /* Wait for nPWRDWN to go low to indicate poweron is done. */ +@@ -431,6 +438,7 @@ static int rpi_touchscreen_probe(struct + + /* Turn off at boot, so we can cleanly sequence powering on. */ + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); ++ usleep_range(20000, 25000); + + /* Look up the DSI host. It needs to probe before we do. */ + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); diff --git a/target/linux/bcm27xx/patches-6.1/950-0867-PCI-brcmstb-Add-BCM2712-support.patch b/target/linux/bcm27xx/patches-6.1/950-0867-PCI-brcmstb-Add-BCM2712-support.patch new file mode 100644 index 0000000000..179d03733e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0867-PCI-brcmstb-Add-BCM2712-support.patch @@ -0,0 +1,1108 @@ +From 29702857d1ab71243ea6c247dfe9b5bc43dd422f Mon Sep 17 00:00:00 2001 +From: Jim Quinlan +Date: Fri, 23 Jun 2023 10:40:57 -0400 +Subject: [PATCH] PCI: brcmstb: Add BCM2712 support + +PCI: brcmstb: differing register offsets on 2712 + +pcie-brcmstb: Add 2712 bridge reset support + +pcie: 2712 PORT_MASK and rescal support + +pcie-brcmstb: don't alter the L1SS debug register + +For reasons unknown, this disables the reference clock + +pcie-brcmstb: fix BAR2 enable and window decode + +Set UBUS ACCESS_EN to let inbound DMA work. Also BCM2712 has grown +an index in the inbound window size decode register. + +PCIe: brcmstb: Enable support for 64 MSI-Xs + +Signed-off-by: Phil Elwell + +pcie-brcmstb: Suppress read error responses + +If the link is down or the EP fails to return a read completion, the +RC's default behaviour is to return an AXI error. This causes fatal +exceptions on A76, so it's better to respond with all 1s instead. + +pcie-brcmstb: increase UBUS timeout to cater for link retrain events + +pcie-brcmstb: Handle additional inbound regions + +Signed-off-by: Phil Elwell + +pcie-brcmstb: Add support for external MSI controller + +pcie-brcmstb: add a reasonable default traffic class to priority map + +BCM2712 supports multiple traffic classes (TCs) with independent +maximally sized transfer queues for each TC. Traffic classes have no +transaction ordering requirements between them, which facilitates +out-of-order completions and arbitration between posted writes for +data streams that have no dependence on each other. + +In addition to the above benefits of splitting endpoint traffic into +individual queues, priorities can be assigned to traffic classes by +a heuristic or deterministic mechanism. The heuristic elevates AXI +QOS priority in accordance with the number of pending transfers in +each TC's queue, but for true priority signalling a forwarding +mechanism using vendor-defined messages is implemented. + +Receipt of a 3 DWORD VDM assigns a priority tag to a TC on-the-fly, +and this tag corresponds to a configurable AXI QOS value. + +As a simple baseline, assign a linear map of AXI QOS to each tag. + +pcie: brcmstb: set up the VDM forwarding interface when setting up QoS + +pcie-brcmstb: add DT bindings for MPS-size Read Completion Mode + +This controller has an optional feature that allows read completion +TLPs to be sized up to the Maximum Packet Size of a configured link. + +This can exceed the Read Completion Boundary of 128B specified in +the PCIe specification, but depending on endpoint support may increase +link read bandwidth significantly. + +pcie-brcmstb: clean up debug messages + +pcie-brcmstb: fix BCM2712A0 PHY PM errata + +The power management clock is 54MHz not 50MHz, so adjust the PM clock period +to suit. Powering off the PHY PLL in L1.2 is unsafe, so force it on. + +pcie-brcmstb: set CLKREQ functionality according to link partner support + +The RC supports either L1 with clock PM or L1 sub-state control, not both +at the same time. Examine the link partner's capabilities to determine +which is the most suitable scheme to use. + +pcie: brcmstb: don't reset block bridges in suspend or removal cases + +BCM2712 has a single rescal block for all three root complexes, and +holding PCIE1's bridge in reset will hang the chip if a different +RC wants to access any of the rescal registers. + +pcie: brcmstb: guard 2712-specific setup with a RC type check + +BCM2711 doesn't implement the UBUS control registers. + +pcie: brcmstb: On 2712 keeping the PLL powered in L1.x is not required + +A separate misconfiguration when enabling SSC (the MDIO registers no +longer do the same thing on BCM2712) had the side-effect of breaking +PLL powerdown and resume sequencing. + +Allow entry into a true L1.2 state where analogue is depowered. + +pcie: brcmstb: Fix reset warning on probe failure + +Signed-off-by: Phil Elwell + +bcm2712: pcie: adjust PHY PLL setup to use a 54MHz input refclk + +Use canned MDIO writes from Broadcom that switch the ref_clk output +pair to run from the internal fractional PLL, and set the internal PLL +to expect a 54MHz input reference clock. + +Gen3 operation is not guaranteed to be stable in this setup, so default +to gen2. + +This only works if the LCPLL is bypassed (requires latest bootloader). + +pcie: brcmstb: add missing register writes + +drivers: pcie: brcmstb: cater for BCM2712C0 bug dropping QoS on the floor + +The AXI QoS value extracted from the request fifo ends up as zero forever. +Disabling this means that "panic" signalling doesn't do anything useful, +but static priorites do work. + +Also align the selected TC:QoS map with RP1's expectations of service. + +Signed-off-by: Jonathan Bell + +drivers: pcie: brcmstb: shuffle TC priorities up to 8 + +Use the range 8-11 which puts the highest below HVS but leaves space +below for other 2712 masters. + +Signed-off-by: Jonathan Bell + +drivers: pcie: brcmstb: optionally enable QoS features by DT for BCM2712 + +It's a bad idea to universally enable "realtime" priorities for TCs +across all the RC instances on the chip. Endpoints other than RP1 may +make use of these, so you don't want e.g. NVMe descriptor fetches getting +higher priority than your remote display. + +Add two optional DT properties controlling the behaviour - FIFO-based +backpressure QoS or "message-based". Message-based signalling is +fundamentally broken due to a chip bug, so it collapses into a set of +static assignments that RP1 needs. + +The default if neither property is specified is to assign everything a +QoS of 0. + +Signed-off-by: Jonathan Bell + +drivers: pcie: brcmstb: adjust completion timeouts for bcm2712 + +Setting the RC config retry timeout makes CRS auto-polling work, but +the UBUS timeout will override the config retry. Both need to be large. + +Signed-off-by: Jonathan Bell +--- + drivers/pci/controller/pcie-brcmstb.c | 507 +++++++++++++++++++++++--- + 1 file changed, 458 insertions(+), 49 deletions(-) + +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -47,11 +48,25 @@ + #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc + #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00 + ++#define PCIE_RC_TL_VDM_CTL0 0x0a20 ++#define PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK 0x10000 ++#define PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK 0x20000 ++#define PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK 0x40000 ++ ++#define PCIE_RC_TL_VDM_CTL1 0x0a0c ++#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID0_MASK 0x0000ffff ++#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID1_MASK 0xffff0000 ++ + #define PCIE_RC_DL_MDIO_ADDR 0x1100 + #define PCIE_RC_DL_MDIO_WR_DATA 0x1104 + #define PCIE_RC_DL_MDIO_RD_DATA 0x1108 + ++#define PCIE_RC_PL_PHY_CTL_15 0x184c ++#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000 ++#define PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK 0xff ++ + #define PCIE_MISC_MISC_CTRL 0x4008 ++#define PCIE_MISC_MISC_CTRL_RCB_MPS_MODE_MASK 0x400 + #define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000 + #define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000 + #define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000 +@@ -71,6 +86,7 @@ + + #define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c + #define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f ++#define PCIE_MISC_RC_BAR1_CONFIG_HI 0x4030 + + #define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034 + #define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f +@@ -78,6 +94,7 @@ + + #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c + #define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f ++#define PCIE_MISC_RC_BAR3_CONFIG_HI 0x4040 + + #define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044 + #define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048 +@@ -86,12 +103,15 @@ + #define PCIE_MISC_MSI_DATA_CONFIG_VAL_32 0xffe06540 + #define PCIE_MISC_MSI_DATA_CONFIG_VAL_8 0xfff86540 + ++#define PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT 0x405c ++ + #define PCIE_MISC_PCIE_CTRL 0x4064 + #define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1 + #define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4 + + #define PCIE_MISC_PCIE_STATUS 0x4068 + #define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80 ++#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK_2712 0x40 + #define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20 + #define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10 + #define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40 +@@ -116,14 +136,73 @@ + #define PCIE_MEM_WIN0_LIMIT_HI(win) \ + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8) + +-#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204 ++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG pcie->reg_offsets[PCIE_HARD_DEBUG] + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000 + #define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK 0x00200000 + ++#define PCIE_MISC_CTRL_1 0x40A0 ++#define PCIE_MISC_CTRL_1_OUTBOUND_TC_MASK 0xf ++#define PCIE_MISC_CTRL_1_OUTBOUND_NO_SNOOP_MASK BIT(3) ++#define PCIE_MISC_CTRL_1_OUTBOUND_RO_MASK BIT(4) ++#define PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK BIT(5) ++ ++#define PCIE_MISC_UBUS_CTRL 0x40a4 ++#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK BIT(13) ++#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK BIT(19) ++ ++#define PCIE_MISC_UBUS_TIMEOUT 0x40A8 ++ ++#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac ++#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0) ++#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_HI 0x40b0 ++ ++#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP 0x40b4 ++#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0) ++ ++/* Additional RC BARs */ ++#define PCIE_MISC_RC_BAR_CONFIG_LO_SIZE_MASK 0x1f ++#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4 ++#define PCIE_MISC_RC_BAR4_CONFIG_HI 0x40d8 ++/* ... */ ++#define PCIE_MISC_RC_BAR10_CONFIG_LO 0x4104 ++#define PCIE_MISC_RC_BAR10_CONFIG_HI 0x4108 ++ ++#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE 0x1 ++#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK 0xfffff000 ++#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK 0xff ++#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO 0x410c ++#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI 0x4110 ++/* ... */ ++#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_LO 0x413c ++#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_HI 0x4140 ++ ++/* AXI priority forwarding - automatic level-based */ ++#define PCIE_MISC_TC_QUEUE_TO_QOS_MAP(x) (0x4160 - (x) * 4) ++/* Defined in quarter-fullness */ ++#define QUEUE_THRESHOLD_34_TO_QOS_MAP_SHIFT 12 ++#define QUEUE_THRESHOLD_23_TO_QOS_MAP_SHIFT 8 ++#define QUEUE_THRESHOLD_12_TO_QOS_MAP_SHIFT 4 ++#define QUEUE_THRESHOLD_01_TO_QOS_MAP_SHIFT 0 ++#define QUEUE_THRESHOLD_MASK 0xf ++ ++/* VDM messages indexing TCs to AXI priorities */ ++/* Indexes 8-15 */ ++#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI 0x4164 ++/* Indexes 0-7 */ ++#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO 0x4168 ++#define VDM_PRIORITY_TO_QOS_MAP_SHIFT(x) (4 * (x)) ++#define VDM_PRIORITY_TO_QOS_MAP_MASK 0xf ++ ++#define PCIE_MISC_AXI_INTF_CTRL 0x416C ++#define AXI_REQFIFO_EN_QOS_PROPAGATION BIT(7) ++#define AXI_BRIDGE_LOW_LATENCY_MODE BIT(6) ++#define AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK 0x3f + +-#define PCIE_INTR2_CPU_BASE 0x4300 ++#define PCIE_MISC_AXI_READ_ERROR_DATA 0x4170 ++ ++#define PCIE_INTR2_CPU_BASE (pcie->reg_offsets[INTR2_CPU]) + #define PCIE_MSI_INTR2_BASE 0x4500 + /* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */ + #define MSI_INT_STATUS 0x0 +@@ -197,6 +276,8 @@ enum { + RGR1_SW_INIT_1, + EXT_CFG_INDEX, + EXT_CFG_DATA, ++ PCIE_HARD_DEBUG, ++ INTR2_CPU, + }; + + enum { +@@ -211,6 +292,7 @@ enum pcie_type { + BCM4908, + BCM7278, + BCM2711, ++ BCM2712, + }; + + struct pcie_cfg_data { +@@ -218,6 +300,7 @@ struct pcie_cfg_data { + const enum pcie_type type; + void (*perst_set)(struct brcm_pcie *pcie, u32 val); + void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val); ++ bool (*rc_mode)(struct brcm_pcie *pcie); + }; + + struct subdev_regulators { +@@ -234,7 +317,7 @@ struct brcm_msi { + struct mutex lock; /* guards the alloc/free operations */ + u64 target_addr; + int irq; +- DECLARE_BITMAP(used, BRCM_INT_PCI_MSI_NR); ++ DECLARE_BITMAP(used, 64); + bool legacy; + /* Some chips have MSIs in bits [31..24] of a shared register. */ + int legacy_shift; +@@ -251,6 +334,7 @@ struct brcm_pcie { + struct device_node *np; + bool ssc; + bool l1ss; ++ bool rcb_mps_mode; + int gen; + u64 msi_target_addr; + struct brcm_msi *msi; +@@ -258,11 +342,14 @@ struct brcm_pcie { + enum pcie_type type; + struct reset_control *rescal; + struct reset_control *perst_reset; ++ struct reset_control *bridge_reset; + int num_memc; + u64 memc_size[PCIE_BRCM_MAX_MEMC]; + u32 hw_rev; ++ u32 qos_map; + void (*perst_set)(struct brcm_pcie *pcie, u32 val); + void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val); ++ bool (*rc_mode)(struct brcm_pcie *pcie); + struct subdev_regulators *sr; + bool ep_wakeup_capable; + }; +@@ -283,8 +370,8 @@ static int brcm_pcie_encode_ibar_size(u6 + if (log2_in >= 12 && log2_in <= 15) + /* Covers 4KB to 32KB (inclusive) */ + return (log2_in - 12) + 0x1c; +- else if (log2_in >= 16 && log2_in <= 35) +- /* Covers 64KB to 32GB, (inclusive) */ ++ else if (log2_in >= 16 && log2_in <= 36) ++ /* Covers 64KB to 64GB, (inclusive) */ + return log2_in - 15; + /* Something is awry so disable */ + return 0; +@@ -381,6 +468,35 @@ static int brcm_pcie_set_ssc(struct brcm + return ssc && pll ? 0 : -EIO; + } + ++static void brcm_pcie_munge_pll(struct brcm_pcie *pcie) ++{ ++ //print "MDIO block 0x1600 written per Dannys instruction" ++ //tmp = pcie_mdio_write(phyad, &h16&, &h50b9&) ++ //tmp = pcie_mdio_write(phyad, &h17&, &hbd1a&) ++ //tmp = pcie_mdio_write(phyad, &h1b&, &h5030&) ++ //tmp = pcie_mdio_write(phyad, &h1e&, &h0007&) ++ ++ u32 tmp; ++ int ret, i; ++ u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e }; ++ u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 }; ++ ++ ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET, ++ 0x1600); ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); ++ dev_dbg(pcie->dev, "PCIE MDIO pre_refclk 0x%02x = 0x%04x\n", ++ regs[i], tmp); ++ } ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]); ++ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); ++ dev_dbg(pcie->dev, "PCIE MDIO post_refclk 0x%02x = 0x%04x\n", ++ regs[i], tmp); ++ } ++ usleep_range(100, 200); ++} ++ + /* Limits operation to a specific generation (1, 2, or 3) */ + static void brcm_pcie_set_gen(struct brcm_pcie *pcie, int gen) + { +@@ -438,6 +554,97 @@ static void brcm_pcie_set_outbound_win(s + writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win)); + } + ++static void brcm_pcie_set_tc_qos(struct brcm_pcie *pcie) ++{ ++ int i; ++ u32 reg; ++ ++ if (pcie->type != BCM2712) ++ return; ++ ++ /* XXX: BCM2712C0 is broken, disable the forwarding search */ ++ reg = readl(pcie->base + PCIE_MISC_AXI_INTF_CTRL); ++ reg &= ~AXI_REQFIFO_EN_QOS_PROPAGATION; ++ writel(reg, pcie->base + PCIE_MISC_AXI_INTF_CTRL); ++ ++ /* Disable VDM reception by default - QoS map defaults to 0 */ ++ reg = readl(pcie->base + PCIE_MISC_CTRL_1); ++ reg &= ~PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK; ++ writel(reg, pcie->base + PCIE_MISC_CTRL_1); ++ ++ if (!of_property_read_u32(pcie->np, "brcm,fifo-qos-map", &pcie->qos_map)) { ++ /* ++ * Backpressure mode - bottom 4 nibbles are QoS for each ++ * quartile of FIFO level. Each TC gets the same map, because ++ * this mode is intended for nonrealtime EPs. ++ */ ++ ++ pcie->qos_map &= 0x0000ffff; ++ for (i = 0; i < 8; i++) ++ writel(pcie->qos_map, pcie->base + PCIE_MISC_TC_QUEUE_TO_QOS_MAP(i)); ++ ++ return; ++ } ++ ++ if (!of_property_read_u32(pcie->np, "brcm,vdm-qos-map", &pcie->qos_map)) { ++ ++ reg = readl(pcie->base + PCIE_MISC_CTRL_1); ++ reg |= PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK; ++ writel(reg, pcie->base + PCIE_MISC_CTRL_1); ++ ++ /* No forwarding means no point separating panic priorities from normal */ ++ writel(pcie->qos_map, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO); ++ writel(pcie->qos_map, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI); ++ ++ /* Match Vendor ID of 0 */ ++ writel(0, pcie->base + PCIE_RC_TL_VDM_CTL1); ++ /* Forward VDMs to priority interface - at least the rx counters work */ ++ reg = readl(pcie->base + PCIE_RC_TL_VDM_CTL0); ++ reg |= PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK | ++ PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK | ++ PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK; ++ writel(reg, pcie->base + PCIE_RC_TL_VDM_CTL0); ++ } ++} ++ ++static void brcm_pcie_config_clkreq(struct brcm_pcie *pcie) ++{ ++ void __iomem *base = pcie->base; ++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); ++ int domain = pci_domain_nr(bridge->bus); ++ const struct pci_bus *bus = pci_find_bus(domain, 1); ++ struct pci_dev *pdev = (struct pci_dev *)bus->devices.next; ++ u32 tmp, link_cap = 0; ++ u16 link_ctl = 0; ++ int clkpm = 0; ++ int substates = 0; ++ ++ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); ++ if ((link_cap & PCI_EXP_LNKCAP_CLKPM)) ++ clkpm = 1; ++ ++ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &link_ctl); ++ if (!(link_ctl & PCI_EXP_LNKCTL_CLKREQ_EN)) ++ clkpm = 0; ++ ++ if (pcie->l1ss && pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS)) ++ substates = 1; ++ ++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; ++ tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; ++ ++ if (substates) ++ tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; ++ else if (clkpm) ++ tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; ++ ++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ ++ if (substates || clkpm) ++ dev_info(pcie->dev, "clkreq control enabled\n"); ++} ++ + static struct irq_chip brcm_msi_irq_chip = { + .name = "BRCM STB PCIe MSI", + .irq_ack = irq_chip_ack_parent, +@@ -455,7 +662,7 @@ static struct msi_domain_info brcm_msi_d + static void brcm_pcie_msi_isr(struct irq_desc *desc) + { + struct irq_chip *chip = irq_desc_get_chip(desc); +- unsigned long status; ++ unsigned long status, virq; + struct brcm_msi *msi; + struct device *dev; + u32 bit; +@@ -467,10 +674,22 @@ static void brcm_pcie_msi_isr(struct irq + status = readl(msi->intr_base + MSI_INT_STATUS); + status >>= msi->legacy_shift; + +- for_each_set_bit(bit, &status, msi->nr) { +- int ret; +- ret = generic_handle_domain_irq(msi->inner_domain, bit); +- if (ret) ++ for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR/*msi->nr*/) { ++ bool found = false; ++ ++ virq = irq_find_mapping(msi->inner_domain, bit); ++ if (virq) { ++ found = true; ++ dev_dbg(dev, "MSI -> %ld\n", virq); ++ generic_handle_irq(virq); ++ } ++ virq = irq_find_mapping(msi->inner_domain, bit + 32); ++ if (virq) { ++ found = true; ++ dev_dbg(dev, "MSI -> %ld\n", virq); ++ generic_handle_irq(virq); ++ } ++ if (!found) + dev_dbg(dev, "unexpected MSI\n"); + } + +@@ -483,7 +702,7 @@ static void brcm_msi_compose_msi_msg(str + + msg->address_lo = lower_32_bits(msi->target_addr); + msg->address_hi = upper_32_bits(msi->target_addr); +- msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | data->hwirq; ++ msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | (data->hwirq & 0x1f); + } + + static int brcm_msi_set_affinity(struct irq_data *irq_data, +@@ -495,7 +714,7 @@ static int brcm_msi_set_affinity(struct + static void brcm_msi_ack_irq(struct irq_data *data) + { + struct brcm_msi *msi = irq_data_get_irq_chip_data(data); +- const int shift_amt = data->hwirq + msi->legacy_shift; ++ const int shift_amt = (data->hwirq & 0x1f) + msi->legacy_shift; + + writel(1 << shift_amt, msi->intr_base + MSI_INT_CLR); + } +@@ -653,7 +872,7 @@ static int brcm_pcie_enable_msi(struct b + msi->legacy_shift = 24; + } else { + msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE; +- msi->nr = BRCM_INT_PCI_MSI_NR; ++ msi->nr = 64; //BRCM_INT_PCI_MSI_NR; + msi->legacy_shift = 0; + } + +@@ -670,7 +889,7 @@ static int brcm_pcie_enable_msi(struct b + } + + /* The controller is capable of serving in both RC and EP roles */ +-static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie) ++static bool brcm_pcie_rc_mode_generic(struct brcm_pcie *pcie) + { + void __iomem *base = pcie->base; + u32 val = readl(base + PCIE_MISC_PCIE_STATUS); +@@ -678,6 +897,14 @@ static bool brcm_pcie_rc_mode(struct brc + return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK, val); + } + ++static bool brcm_pcie_rc_mode_2712(struct brcm_pcie *pcie) ++{ ++ void __iomem *base = pcie->base; ++ u32 val = readl(base + PCIE_MISC_PCIE_STATUS); ++ ++ return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK_2712, val) | 1; //XXX ++} ++ + static bool brcm_pcie_link_up(struct brcm_pcie *pcie) + { + u32 val = readl(pcie->base + PCIE_MISC_PCIE_STATUS); +@@ -749,6 +976,18 @@ static inline void brcm_pcie_bridge_sw_i + writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie)); + } + ++static inline void brcm_pcie_bridge_sw_init_set_2712(struct brcm_pcie *pcie, u32 val) ++{ ++ if (WARN_ONCE(!pcie->bridge_reset, ++ "missing bridge reset controller\n")) ++ return; ++ ++ if (val) ++ reset_control_assert(pcie->bridge_reset); ++ else ++ reset_control_deassert(pcie->bridge_reset); ++} ++ + static inline void brcm_pcie_perst_set_4908(struct brcm_pcie *pcie, u32 val) + { + if (WARN_ONCE(!pcie->perst_reset, "missing PERST# reset controller\n")) +@@ -770,6 +1009,16 @@ static inline void brcm_pcie_perst_set_7 + writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL); + } + ++static inline void brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val) ++{ ++ u32 tmp; ++ ++ /* Perst bit has moved and assert value is 0 */ ++ tmp = readl(pcie->base + PCIE_MISC_PCIE_CTRL); ++ u32p_replace_bits(&tmp, !val, PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK); ++ writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL); ++} ++ + static inline void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val) + { + u32 tmp; +@@ -796,6 +1045,8 @@ static inline int brcm_pcie_get_rc_bar2_ + size += entry->res->end - entry->res->start + 1; + if (pcie_beg < lowest_pcie_addr) + lowest_pcie_addr = pcie_beg; ++ if (pcie->type == BCM2711 || pcie->type == BCM2712) ++ break; // Only consider the first entry + } + + if (lowest_pcie_addr == ~(u64)0) { +@@ -866,6 +1117,30 @@ static inline int brcm_pcie_get_rc_bar2_ + return 0; + } + ++static int brcm_pcie_get_rc_bar_n(struct brcm_pcie *pcie, ++ int idx, ++ u64 *rc_bar_cpu, ++ u64 *rc_bar_size, ++ u64 *rc_bar_pci) ++{ ++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); ++ struct resource_entry *entry; ++ int i = 0; ++ ++ resource_list_for_each_entry(entry, &bridge->dma_ranges) { ++ if (i == idx) { ++ *rc_bar_cpu = entry->res->start; ++ *rc_bar_size = entry->res->end - entry->res->start + 1; ++ *rc_bar_pci = entry->res->start - entry->offset; ++ return 0; ++ } ++ ++ i++; ++ } ++ ++ return -EINVAL; ++} ++ + static int brcm_pcie_setup(struct brcm_pcie *pcie) + { + u64 rc_bar2_offset, rc_bar2_size; +@@ -874,11 +1149,14 @@ static int brcm_pcie_setup(struct brcm_p + struct resource_entry *entry; + u32 tmp, burst, aspm_support; + int num_out_wins = 0; +- int ret, memc; ++ int ret, memc, count, i; + + /* Reset the bridge */ + pcie->bridge_sw_init_set(pcie, 1); +- pcie->perst_set(pcie, 1); ++ ++ /* Ensure that PERST# is asserted; some bootloaders may deassert it. */ ++ if (pcie->type == BCM2711) ++ pcie->perst_set(pcie, 1); + + usleep_range(100, 200); + +@@ -894,6 +1172,17 @@ static int brcm_pcie_setup(struct brcm_p + /* Wait for SerDes to be stable */ + usleep_range(100, 200); + ++ if (pcie->type == BCM2712) { ++ /* Allow a 54MHz (xosc) refclk source */ ++ brcm_pcie_munge_pll(pcie); ++ /* Fix for L1SS errata */ ++ tmp = readl(base + PCIE_RC_PL_PHY_CTL_15); ++ tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK; ++ /* PM clock period is 18.52ns (round down) */ ++ tmp |= 0x12; ++ writel(tmp, base + PCIE_RC_PL_PHY_CTL_15); ++ } ++ + /* + * SCB_MAX_BURST_SIZE is a two bit field. For GENERIC chips it + * is encoded as 0=128, 1=256, 2=512, 3=Rsvd, for BCM7278 it +@@ -903,18 +1192,25 @@ static int brcm_pcie_setup(struct brcm_p + burst = 0x1; /* 256 bytes */ + else if (pcie->type == BCM2711) + burst = 0x0; /* 128 bytes */ ++ else if (pcie->type == BCM2712) ++ burst = 0x1; /* 128 bytes */ + else if (pcie->type == BCM7278) + burst = 0x3; /* 512 bytes */ + else + burst = 0x2; /* 512 bytes */ + +- /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */ ++ /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN, RCB_MPS_MODE */ + tmp = readl(base + PCIE_MISC_MISC_CTRL); + u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK); + u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK); + u32p_replace_bits(&tmp, burst, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK); ++ if (pcie->rcb_mps_mode) ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_RCB_MPS_MODE_MASK); ++ dev_info(pcie->dev, "setting SCB_ACCESS_EN, READ_UR_MODE, MAX_BURST_SIZE\n"); + writel(tmp, base + PCIE_MISC_MISC_CTRL); + ++ brcm_pcie_set_tc_qos(pcie); ++ + ret = brcm_pcie_get_rc_bar2_size_and_offset(pcie, &rc_bar2_size, + &rc_bar2_offset); + if (ret) +@@ -927,7 +1223,11 @@ static int brcm_pcie_setup(struct brcm_p + writel(upper_32_bits(rc_bar2_offset), + base + PCIE_MISC_RC_BAR2_CONFIG_HI); + ++ tmp = readl(base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK); ++ writel(tmp, base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP); + tmp = readl(base + PCIE_MISC_MISC_CTRL); ++ + for (memc = 0; memc < pcie->num_memc; memc++) { + u32 scb_size_val = ilog2(pcie->memc_size[memc]) - 15; + +@@ -938,8 +1238,32 @@ static int brcm_pcie_setup(struct brcm_p + else if (memc == 2) + u32p_replace_bits(&tmp, scb_size_val, SCB_SIZE_MASK(2)); + } ++ + writel(tmp, base + PCIE_MISC_MISC_CTRL); + ++ if (pcie->type == BCM2712) { ++ /* Suppress AXI error responses and return 1s for read failures */ ++ tmp = readl(base + PCIE_MISC_UBUS_CTRL); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK); ++ writel(tmp, base + PCIE_MISC_UBUS_CTRL); ++ writel(0xffffffff, base + PCIE_MISC_AXI_READ_ERROR_DATA); ++ ++ /* ++ * Adjust timeouts. The UBUS timeout also affects CRS ++ * completion retries, as the request will get terminated if ++ * either timeout expires, so both have to be a large value ++ * (in clocks of 750MHz). ++ * Set UBUS timeout to 250ms, then set RC config retry timeout ++ * to be ~240ms. ++ * ++ * Setting CRSVis=1 will stop the core from blocking on a CRS ++ * response, but does require the device to be well-behaved... ++ */ ++ writel(0xB2D0000, base + PCIE_MISC_UBUS_TIMEOUT); ++ writel(0xABA0000, base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT); ++ } ++ + /* + * We ideally want the MSI target address to be located in the 32bit + * addressable memory area. Some devices might depend on it. This is +@@ -952,7 +1276,7 @@ static int brcm_pcie_setup(struct brcm_p + else + pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB; + +- if (!brcm_pcie_rc_mode(pcie)) { ++ if (!pcie->rc_mode(pcie)) { + dev_err(pcie->dev, "PCIe RC controller misconfigured as Endpoint\n"); + return -EINVAL; + } +@@ -976,6 +1300,38 @@ static int brcm_pcie_setup(struct brcm_p + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK); + writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); + ++ /* program additional inbound windows (RC_BAR4..RC_BAR10) */ ++ count = (pcie->type == BCM2712) ? 7 : 0; ++ for (i = 0; i < count; i++) { ++ u64 bar_cpu, bar_size, bar_pci; ++ ++ ret = brcm_pcie_get_rc_bar_n(pcie, 1 + i, &bar_cpu, &bar_size, ++ &bar_pci); ++ if (ret) ++ break; ++ ++ tmp = lower_32_bits(bar_pci); ++ u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(bar_size), ++ PCIE_MISC_RC_BAR_CONFIG_LO_SIZE_MASK); ++ writel(tmp, base + PCIE_MISC_RC_BAR4_CONFIG_LO + i * 8); ++ writel(upper_32_bits(bar_pci), ++ base + PCIE_MISC_RC_BAR4_CONFIG_HI + i * 8); ++ ++ tmp = upper_32_bits(bar_cpu) & ++ PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK; ++ writel(tmp, ++ base + PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI + i * 8); ++ tmp = lower_32_bits(bar_cpu) & ++ PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK; ++ writel(tmp | PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE, ++ base + PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO + i * 8); ++ } ++ ++ if (pcie->gen) { ++ dev_info(pcie->dev, "Forcing gen %d\n", pcie->gen); ++ brcm_pcie_set_gen(pcie, pcie->gen); ++ } ++ + /* + * For config space accesses on the RC, show the right class for + * a PCIe-PCIe bridge (the default setting is to be EP mode). +@@ -1031,7 +1387,6 @@ static int brcm_pcie_start_link(struct b + void __iomem *base = pcie->base; + u16 nlw, cls, lnksta; + bool ssc_good = false; +- u32 tmp; + int ret, i; + + /* Unassert the fundamental reset */ +@@ -1067,6 +1422,7 @@ static int brcm_pcie_start_link(struct b + dev_err(dev, "failed attempt to enter ssc mode\n"); + } + ++ + lnksta = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA); + cls = FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta); + nlw = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta); +@@ -1074,27 +1430,6 @@ static int brcm_pcie_start_link(struct b + pci_speed_string(pcie_link_speed[cls]), nlw, + ssc_good ? "(SSC)" : "(!SSC)"); + +- tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); +- if (pcie->l1ss) { +- /* +- * Enable CLKREQ# signalling include L1 Substate control of +- * the CLKREQ# signal and the external reference clock buffer. +- * meet requirement for Endpoints that require CLKREQ# +- * assertion to clock active within 400ns. +- */ +- tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; +- tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; +- } else { +- /* +- * Refclk from RC should be gated with CLKREQ# input when +- * ASPM L0s,L1 is enabled => setting the CLKREQ_DEBUG_ENABLE +- * field to 1. +- */ +- tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; +- tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; +- } +- writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); +- + return 0; + } + +@@ -1202,6 +1537,7 @@ static void brcm_pcie_enter_l23(struct b + + static int brcm_phy_cntl(struct brcm_pcie *pcie, const int start) + { ++#if 0 + static const u32 shifts[PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_NFLDS] = { + PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_SHIFT, + PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_RESET_SHIFT, +@@ -1234,6 +1570,9 @@ static int brcm_phy_cntl(struct brcm_pci + dev_err(pcie->dev, "failed to %s phy\n", (start ? "start" : "stop")); + + return ret; ++#else ++ return 0; ++#endif + } + + static inline int brcm_phy_start(struct brcm_pcie *pcie) +@@ -1266,6 +1605,12 @@ static void brcm_pcie_turn_off(struct br + u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK); + writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); + ++ /* ++ * Shutting down this bridge on pcie1 means accesses to rescal block ++ * will hang the chip if another RC wants to assert/deassert rescal. ++ */ ++ if (pcie->type == BCM2712) ++ return; + /* Shutdown PCIe bridge */ + pcie->bridge_sw_init_set(pcie, 1); + } +@@ -1296,9 +1641,9 @@ static int brcm_pcie_suspend_noirq(struc + if (brcm_phy_stop(pcie)) + dev_err(dev, "Could not stop phy for suspend\n"); + +- ret = reset_control_rearm(pcie->rescal); ++ ret = reset_control_assert(pcie->rescal); + if (ret) { +- dev_err(dev, "Could not rearm rescal reset\n"); ++ dev_err(dev, "Could not assert rescal reset\n"); + return ret; + } + +@@ -1393,7 +1738,7 @@ err_regulator: + if (pcie->sr) + regulator_bulk_disable(pcie->sr->num_supplies, pcie->sr->supplies); + err_reset: +- reset_control_rearm(pcie->rescal); ++ reset_control_assert(pcie->rescal); + err_disable_clk: + clk_disable_unprepare(pcie->clk); + return ret; +@@ -1405,8 +1750,8 @@ static void __brcm_pcie_remove(struct br + brcm_pcie_turn_off(pcie); + if (brcm_phy_stop(pcie)) + dev_err(pcie->dev, "Could not stop phy\n"); +- if (reset_control_rearm(pcie->rescal)) +- dev_err(pcie->dev, "Could not rearm rescal reset\n"); ++ if (reset_control_assert(pcie->rescal)) ++ dev_err(pcie->dev, "Could not assert rescal reset\n"); + clk_disable_unprepare(pcie->clk); + } + +@@ -1426,12 +1771,16 @@ static const int pcie_offsets[] = { + [RGR1_SW_INIT_1] = 0x9210, + [EXT_CFG_INDEX] = 0x9000, + [EXT_CFG_DATA] = 0x9004, ++ [PCIE_HARD_DEBUG] = 0x4204, ++ [INTR2_CPU] = 0x4300, + }; + + static const int pcie_offsets_bmips_7425[] = { + [RGR1_SW_INIT_1] = 0x8010, + [EXT_CFG_INDEX] = 0x8300, + [EXT_CFG_DATA] = 0x8304, ++ [PCIE_HARD_DEBUG] = 0x4204, ++ [INTR2_CPU] = 0x4300, + }; + + static const struct pcie_cfg_data generic_cfg = { +@@ -1439,6 +1788,7 @@ static const struct pcie_cfg_data generi + .type = GENERIC, + .perst_set = brcm_pcie_perst_set_generic, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const struct pcie_cfg_data bcm7425_cfg = { +@@ -1446,6 +1796,7 @@ static const struct pcie_cfg_data bcm742 + .type = BCM7425, + .perst_set = brcm_pcie_perst_set_generic, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const struct pcie_cfg_data bcm7435_cfg = { +@@ -1460,12 +1811,15 @@ static const struct pcie_cfg_data bcm490 + .type = BCM4908, + .perst_set = brcm_pcie_perst_set_4908, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const int pcie_offset_bcm7278[] = { + [RGR1_SW_INIT_1] = 0xc010, + [EXT_CFG_INDEX] = 0x9000, + [EXT_CFG_DATA] = 0x9004, ++ [PCIE_HARD_DEBUG] = 0x4204, ++ [INTR2_CPU] = 0x4300, + }; + + static const struct pcie_cfg_data bcm7278_cfg = { +@@ -1473,6 +1827,7 @@ static const struct pcie_cfg_data bcm727 + .type = BCM7278, + .perst_set = brcm_pcie_perst_set_7278, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_7278, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const struct pcie_cfg_data bcm2711_cfg = { +@@ -1480,10 +1835,27 @@ static const struct pcie_cfg_data bcm271 + .type = BCM2711, + .perst_set = brcm_pcie_perst_set_generic, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, ++}; ++ ++static const int pcie_offsets_bcm2712[] = { ++ [EXT_CFG_INDEX] = 0x9000, ++ [EXT_CFG_DATA] = 0x9004, ++ [PCIE_HARD_DEBUG] = 0x4304, ++ [INTR2_CPU] = 0x4400, ++}; ++ ++static const struct pcie_cfg_data bcm2712_cfg = { ++ .offsets = pcie_offsets_bcm2712, ++ .type = BCM2712, ++ .perst_set = brcm_pcie_perst_set_2712, ++ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_2712, ++ .rc_mode = brcm_pcie_rc_mode_2712, + }; + + static const struct of_device_id brcm_pcie_match[] = { + { .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg }, ++ { .compatible = "brcm,bcm2712-pcie", .data = &bcm2712_cfg }, + { .compatible = "brcm,bcm4908-pcie", .data = &bcm4908_cfg }, + { .compatible = "brcm,bcm7211-pcie", .data = &generic_cfg }, + { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg }, +@@ -1524,7 +1896,7 @@ static int brcm_pcie_probe(struct platfo + + data = of_device_get_match_data(&pdev->dev); + if (!data) { +- pr_err("failed to look up compatible string\n"); ++ dev_err(&pdev->dev, "failed to look up compatible string\n"); + return -EINVAL; + } + +@@ -1535,6 +1907,7 @@ static int brcm_pcie_probe(struct platfo + pcie->type = data->type; + pcie->perst_set = data->perst_set; + pcie->bridge_sw_init_set = data->bridge_sw_init_set; ++ pcie->rc_mode = data->rc_mode; + + pcie->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pcie->base)) +@@ -1549,6 +1922,7 @@ static int brcm_pcie_probe(struct platfo + + pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc"); + pcie->l1ss = of_property_read_bool(np, "brcm,enable-l1ss"); ++ pcie->rcb_mps_mode = of_property_read_bool(np, "brcm,enable-mps-rcb"); + + ret = clk_prepare_enable(pcie->clk); + if (ret) { +@@ -1565,14 +1939,20 @@ static int brcm_pcie_probe(struct platfo + clk_disable_unprepare(pcie->clk); + return PTR_ERR(pcie->perst_reset); + } ++ pcie->bridge_reset = ++ devm_reset_control_get_optional_exclusive(&pdev->dev, "bridge"); ++ if (IS_ERR(pcie->bridge_reset)) { ++ clk_disable_unprepare(pcie->clk); ++ return PTR_ERR(pcie->bridge_reset); ++ } + +- ret = reset_control_reset(pcie->rescal); ++ ret = reset_control_deassert(pcie->rescal); + if (ret) + dev_err(&pdev->dev, "failed to deassert 'rescal'\n"); + + ret = brcm_phy_start(pcie); + if (ret) { +- reset_control_rearm(pcie->rescal); ++ reset_control_assert(pcie->rescal); + clk_disable_unprepare(pcie->clk); + return ret; + } +@@ -1595,6 +1975,33 @@ static int brcm_pcie_probe(struct platfo + dev_err(pcie->dev, "probe of internal MSI failed"); + goto fail; + } ++ } else if (pci_msi_enabled() && msi_np != pcie->np) { ++ /* Use RC_BAR1 for MIP access */ ++ u64 msi_pci_addr; ++ u64 msi_phys_addr; ++ ++ if (of_property_read_u64(msi_np, "brcm,msi-pci-addr", &msi_pci_addr)) { ++ dev_err(pcie->dev, "Unable to find MSI PCI address\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ if (of_property_read_u64(msi_np, "reg", &msi_phys_addr)) { ++ dev_err(pcie->dev, "Unable to find MSI physical address\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ writel(lower_32_bits(msi_pci_addr) | brcm_pcie_encode_ibar_size(0x1000), ++ pcie->base + PCIE_MISC_RC_BAR1_CONFIG_LO); ++ writel(upper_32_bits(msi_pci_addr), ++ pcie->base + PCIE_MISC_RC_BAR1_CONFIG_HI); ++ ++ writel(lower_32_bits(msi_phys_addr) | ++ PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK, ++ pcie->base + PCIE_MISC_UBUS_BAR1_CONFIG_REMAP); ++ writel(upper_32_bits(msi_phys_addr), ++ pcie->base + PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_HI); + } + + bridge->ops = pcie->type == BCM7425 ? &brcm7425_pcie_ops : &brcm_pcie_ops; +@@ -1611,6 +2018,8 @@ static int brcm_pcie_probe(struct platfo + return ret; + } + ++ brcm_pcie_config_clkreq(pcie); ++ + return 0; + + fail: diff --git a/target/linux/bcm27xx/patches-6.1/950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch b/target/linux/bcm27xx/patches-6.1/950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch new file mode 100644 index 0000000000..3b50329ab1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch @@ -0,0 +1,42 @@ +From 9a11300e46344917226b986a8740e7581d66adf3 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 7 Feb 2022 09:20:49 +0000 +Subject: [PATCH] V4L2: Add PiSP opaque formats to V4L2 + +Signed-off-by: Naushir Patuck +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 4 +++- + include/uapi/linux/videodev2.h | 7 +++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1452,7 +1452,9 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_NV12M_10BE_8L128: descr = "10-bit NV12M (8x128 Linear, BE)"; break; + case V4L2_META_FMT_SENSOR_DATA: descr = "Sensor Ancillary Metadata"; break; + case V4L2_META_FMT_BCM2835_ISP_STATS: descr = "BCM2835 ISP Image Statistics"; break; +- case V4L2_META_FMT_RPI_BE_CFG: descr = "PiSP Config format"; break; ++ case V4L2_META_FMT_RPI_BE_CFG: descr = "PiSP BE Config format"; break; ++ case V4L2_META_FMT_RPI_FE_CFG: descr = "PiSP FE Config format"; break; ++ case V4L2_META_FMT_RPI_FE_STATS: descr = "PiSP FE Statistics format"; break; + + default: + /* Compressed formats */ +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -826,8 +826,15 @@ struct v4l2_pix_format { + #define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A Statistics */ + + /* The metadata format identifier for our configuration buffers. */ ++/* The metadata format identifier for BE configuration buffers. */ + #define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') + ++/* The metadata format identifier for FE configuration buffers. */ ++#define V4L2_META_FMT_RPI_FE_CFG v4l2_fourcc('R', 'P', 'F', 'C') ++ ++/* The metadata format identifier for FE configuration buffers. */ ++#define V4L2_META_FMT_RPI_FE_STATS v4l2_fourcc('R', 'P', 'F', 'S') ++ + /* priv field value to indicates that subsequent fields are valid. */ + #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe + diff --git a/target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch b/target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch new file mode 100644 index 0000000000..6836922b7c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch @@ -0,0 +1,39 @@ +From 01f31f4145d49a30eb553c65ea755dde8dba1de0 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 2 Mar 2022 16:10:50 +0000 +Subject: [PATCH] V4L2: Add PiSP compressed formats to V4L2 + +Signed-off-by: Naushir Patuck +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++++ + include/uapi/linux/videodev2.h | 6 +++++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1507,6 +1507,10 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break; + case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break; + case V4L2_PIX_FMT_RPI_BE: descr = "PiSP Opaque Format"; break; ++ case V4L2_PIX_FMT_PISP_COMP_RGGB: ++ case V4L2_PIX_FMT_PISP_COMP_GRBG: ++ case V4L2_PIX_FMT_PISP_COMP_GBRG: ++ case V4L2_PIX_FMT_PISP_COMP_BGGR: descr = "PiSP Bayer Compressed Format"; break; + default: + if (fmt->description[0]) + return; +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -794,7 +794,11 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_IPU3_SRGGB10 v4l2_fourcc('i', 'p', '3', 'r') /* IPU3 packed 10-bit RGGB bayer */ + + /* The pixel format for all our buffers (the precise format is found in the config buffer). */ +-#define V4L2_PIX_FMT_RPI_BE v4l2_fourcc('R', 'P', 'B', 'P') ++#define V4L2_PIX_FMT_RPI_BE v4l2_fourcc('R', 'P', 'B', 'P') ++#define V4L2_PIX_FMT_PISP_COMP_RGGB v4l2_fourcc('P', 'C', 'R', 'G') ++#define V4L2_PIX_FMT_PISP_COMP_GRBG v4l2_fourcc('P', 'C', 'G', 'R') ++#define V4L2_PIX_FMT_PISP_COMP_GBRG v4l2_fourcc('P', 'C', 'G', 'B') ++#define V4L2_PIX_FMT_PISP_COMP_BGGR v4l2_fourcc('P', 'C', 'B', 'G') + + /* SDR formats - used only for Software Defined Radio devices */ + #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch b/target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch new file mode 100644 index 0000000000..9e98dd0345 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch @@ -0,0 +1,249 @@ +From c93f469dabdbed822e5abeb5283d79fc9faa858c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 28 Oct 2022 14:10:34 +0100 +Subject: [PATCH] dt-binding: mfd: Add binding for Raspberry Pi RP1 + +Signed-off-by: Phil Elwell +--- + include/dt-bindings/mfd/rp1.h | 235 ++++++++++++++++++++++++++++++++++ + 1 file changed, 235 insertions(+) + create mode 100644 include/dt-bindings/mfd/rp1.h + +--- /dev/null ++++ b/include/dt-bindings/mfd/rp1.h +@@ -0,0 +1,235 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * This header provides constants for the PY MFD. ++ */ ++ ++#ifndef _RP1_H ++#define _RP1_H ++ ++/* Address map */ ++#define RP1_SYSINFO_BASE 0x000000 ++#define RP1_TBMAN_BASE 0x004000 ++#define RP1_SYSCFG_BASE 0x008000 ++#define RP1_OTP_BASE 0x00c000 ++#define RP1_POWER_BASE 0x010000 ++#define RP1_RESETS_BASE 0x014000 ++#define RP1_CLOCKS_BANK_DEFAULT_BASE 0x018000 ++#define RP1_CLOCKS_BANK_VIDEO_BASE 0x01c000 ++#define RP1_PLL_SYS_BASE 0x020000 ++#define RP1_PLL_AUDIO_BASE 0x024000 ++#define RP1_PLL_VIDEO_BASE 0x028000 ++#define RP1_UART0_BASE 0x030000 ++#define RP1_UART1_BASE 0x034000 ++#define RP1_UART2_BASE 0x038000 ++#define RP1_UART3_BASE 0x03c000 ++#define RP1_UART4_BASE 0x040000 ++#define RP1_UART5_BASE 0x044000 ++#define RP1_SPI8_BASE 0x04c000 ++#define RP1_SPI0_BASE 0x050000 ++#define RP1_SPI1_BASE 0x054000 ++#define RP1_SPI2_BASE 0x058000 ++#define RP1_SPI3_BASE 0x05c000 ++#define RP1_SPI4_BASE 0x060000 ++#define RP1_SPI5_BASE 0x064000 ++#define RP1_SPI6_BASE 0x068000 ++#define RP1_SPI7_BASE 0x06c000 ++#define RP1_I2C0_BASE 0x070000 ++#define RP1_I2C1_BASE 0x074000 ++#define RP1_I2C2_BASE 0x078000 ++#define RP1_I2C3_BASE 0x07c000 ++#define RP1_I2C4_BASE 0x080000 ++#define RP1_I2C5_BASE 0x084000 ++#define RP1_I2C6_BASE 0x088000 ++#define RP1_AUDIO_IN_BASE 0x090000 ++#define RP1_AUDIO_OUT_BASE 0x094000 ++#define RP1_PWM0_BASE 0x098000 ++#define RP1_PWM1_BASE 0x09c000 ++#define RP1_I2S0_BASE 0x0a0000 ++#define RP1_I2S1_BASE 0x0a4000 ++#define RP1_I2S2_BASE 0x0a8000 ++#define RP1_TIMER_BASE 0x0ac000 ++#define RP1_SDIO0_APBS_BASE 0x0b0000 ++#define RP1_SDIO1_APBS_BASE 0x0b4000 ++#define RP1_BUSFABRIC_MONITOR_BASE 0x0c0000 ++#define RP1_BUSFABRIC_AXISHIM_BASE 0x0c4000 ++#define RP1_ADC_BASE 0x0c8000 ++#define RP1_IO_BANK0_BASE 0x0d0000 ++#define RP1_IO_BANK1_BASE 0x0d4000 ++#define RP1_IO_BANK2_BASE 0x0d8000 ++#define RP1_SYS_RIO0_BASE 0x0e0000 ++#define RP1_SYS_RIO1_BASE 0x0e4000 ++#define RP1_SYS_RIO2_BASE 0x0e8000 ++#define RP1_PADS_BANK0_BASE 0x0f0000 ++#define RP1_PADS_BANK1_BASE 0x0f4000 ++#define RP1_PADS_BANK2_BASE 0x0f8000 ++#define RP1_PADS_ETH_BASE 0x0fc000 ++#define RP1_ETH_IP_BASE 0x100000 ++#define RP1_ETH_CFG_BASE 0x104000 ++#define RP1_PCIE_APBS_BASE 0x108000 ++#define RP1_MIPI0_CSIDMA_BASE 0x110000 ++#define RP1_MIPI0_CSIHOST_BASE 0x114000 ++#define RP1_MIPI0_DSIDMA_BASE 0x118000 ++#define RP1_MIPI0_DSIHOST_BASE 0x11c000 ++#define RP1_MIPI0_MIPICFG_BASE 0x120000 ++#define RP1_MIPI0_ISP_BASE 0x124000 ++#define RP1_MIPI1_CSIDMA_BASE 0x128000 ++#define RP1_MIPI1_CSIHOST_BASE 0x12c000 ++#define RP1_MIPI1_DSIDMA_BASE 0x130000 ++#define RP1_MIPI1_DSIHOST_BASE 0x134000 ++#define RP1_MIPI1_MIPICFG_BASE 0x138000 ++#define RP1_MIPI1_ISP_BASE 0x13c000 ++#define RP1_VIDEO_OUT_CFG_BASE 0x140000 ++#define RP1_VIDEO_OUT_VEC_BASE 0x144000 ++#define RP1_VIDEO_OUT_DPI_BASE 0x148000 ++#define RP1_XOSC_BASE 0x150000 ++#define RP1_WATCHDOG_BASE 0x154000 ++#define RP1_DMA_TICK_BASE 0x158000 ++#define RP1_SDIO_CLOCKS_BASE 0x15c000 ++#define RP1_USBHOST0_APBS_BASE 0x160000 ++#define RP1_USBHOST1_APBS_BASE 0x164000 ++#define RP1_ROSC0_BASE 0x168000 ++#define RP1_ROSC1_BASE 0x16c000 ++#define RP1_VBUSCTRL_BASE 0x170000 ++#define RP1_TICKS_BASE 0x174000 ++#define RP1_PIO_APBS_BASE 0x178000 ++#define RP1_SDIO0_AHBLS_BASE 0x180000 ++#define RP1_SDIO1_AHBLS_BASE 0x184000 ++#define RP1_DMA_BASE 0x188000 ++#define RP1_RAM_BASE 0x1c0000 ++#define RP1_RAM_SIZE 0x020000 ++#define RP1_USBHOST0_AXIS_BASE 0x200000 ++#define RP1_USBHOST1_AXIS_BASE 0x300000 ++#define RP1_EXAC_BASE 0x400000 ++ ++/* Interrupts */ ++ ++#define RP1_INT_IO_BANK0 0 ++#define RP1_INT_IO_BANK1 1 ++#define RP1_INT_IO_BANK2 2 ++#define RP1_INT_AUDIO_IN 3 ++#define RP1_INT_AUDIO_OUT 4 ++#define RP1_INT_PWM0 5 ++#define RP1_INT_ETH 6 ++#define RP1_INT_I2C0 7 ++#define RP1_INT_I2C1 8 ++#define RP1_INT_I2C2 9 ++#define RP1_INT_I2C3 10 ++#define RP1_INT_I2C4 11 ++#define RP1_INT_I2C5 12 ++#define RP1_INT_I2C6 13 ++#define RP1_INT_I2S0 14 ++#define RP1_INT_I2S1 15 ++#define RP1_INT_I2S2 16 ++#define RP1_INT_SDIO0 17 ++#define RP1_INT_SDIO1 18 ++#define RP1_INT_SPI0 19 ++#define RP1_INT_SPI1 20 ++#define RP1_INT_SPI2 21 ++#define RP1_INT_SPI3 22 ++#define RP1_INT_SPI4 23 ++#define RP1_INT_SPI5 24 ++#define RP1_INT_UART0 25 ++#define RP1_INT_TIMER_0 26 ++#define RP1_INT_TIMER_1 27 ++#define RP1_INT_TIMER_2 28 ++#define RP1_INT_TIMER_3 29 ++#define RP1_INT_USBHOST0 30 ++#define RP1_INT_USBHOST0_0 31 ++#define RP1_INT_USBHOST0_1 32 ++#define RP1_INT_USBHOST0_2 33 ++#define RP1_INT_USBHOST0_3 34 ++#define RP1_INT_USBHOST1 35 ++#define RP1_INT_USBHOST1_0 36 ++#define RP1_INT_USBHOST1_1 37 ++#define RP1_INT_USBHOST1_2 38 ++#define RP1_INT_USBHOST1_3 39 ++#define RP1_INT_DMA 40 ++#define RP1_INT_PWM1 41 ++#define RP1_INT_UART1 42 ++#define RP1_INT_UART2 43 ++#define RP1_INT_UART3 44 ++#define RP1_INT_UART4 45 ++#define RP1_INT_UART5 46 ++#define RP1_INT_MIPI0 47 ++#define RP1_INT_MIPI1 48 ++#define RP1_INT_VIDEO_OUT 49 ++#define RP1_INT_PIO_0 50 ++#define RP1_INT_PIO_1 51 ++#define RP1_INT_ADC_FIFO 52 ++#define RP1_INT_PCIE_OUT 53 ++#define RP1_INT_SPI6 54 ++#define RP1_INT_SPI7 55 ++#define RP1_INT_SPI8 56 ++#define RP1_INT_SYSCFG 58 ++#define RP1_INT_CLOCKS_DEFAULT 59 ++#define RP1_INT_VBUSCTRL 60 ++#define RP1_INT_PROC_MISC 57 ++#define RP1_INT_END 61 ++ ++/* DMA peripherals (for pacing) */ ++#define RP1_DMA_I2C0_RX 0x0 ++#define RP1_DMA_I2C0_TX 0x1 ++#define RP1_DMA_I2C1_RX 0x2 ++#define RP1_DMA_I2C1_TX 0x3 ++#define RP1_DMA_I2C2_RX 0x4 ++#define RP1_DMA_I2C2_TX 0x5 ++#define RP1_DMA_I2C3_RX 0x6 ++#define RP1_DMA_I2C3_TX 0x7 ++#define RP1_DMA_I2C4_RX 0x8 ++#define RP1_DMA_I2C4_TX 0x9 ++#define RP1_DMA_I2C5_RX 0xa ++#define RP1_DMA_I2C5_TX 0xb ++#define RP1_DMA_SPI0_RX 0xc ++#define RP1_DMA_SPI0_TX 0xd ++#define RP1_DMA_SPI1_RX 0xe ++#define RP1_DMA_SPI1_TX 0xf ++#define RP1_DMA_SPI2_RX 0x10 ++#define RP1_DMA_SPI2_TX 0x11 ++#define RP1_DMA_SPI3_RX 0x12 ++#define RP1_DMA_SPI3_TX 0x13 ++#define RP1_DMA_SPI4_RX 0x14 ++#define RP1_DMA_SPI4_TX 0x15 ++#define RP1_DMA_SPI5_RX 0x16 ++#define RP1_DMA_SPI5_TX 0x17 ++#define RP1_DMA_PWM0 0x18 ++#define RP1_DMA_UART0_RX 0x19 ++#define RP1_DMA_UART0_TX 0x1a ++#define RP1_DMA_AUDIO_IN_CH0 0x1b ++#define RP1_DMA_AUDIO_IN_CH1 0x1c ++#define RP1_DMA_AUDIO_OUT 0x1d ++#define RP1_DMA_PWM1 0x1e ++#define RP1_DMA_I2S0_RX 0x1f ++#define RP1_DMA_I2S0_TX 0x20 ++#define RP1_DMA_I2S1_RX 0x21 ++#define RP1_DMA_I2S1_TX 0x22 ++#define RP1_DMA_I2S2_RX 0x23 ++#define RP1_DMA_I2S2_TX 0x24 ++#define RP1_DMA_UART1_RX 0x25 ++#define RP1_DMA_UART1_TX 0x26 ++#define RP1_DMA_UART2_RX 0x27 ++#define RP1_DMA_UART2_TX 0x28 ++#define RP1_DMA_UART3_RX 0x29 ++#define RP1_DMA_UART3_TX 0x2a ++#define RP1_DMA_UART4_RX 0x2b ++#define RP1_DMA_UART4_TX 0x2c ++#define RP1_DMA_UART5_RX 0x2d ++#define RP1_DMA_UART5_TX 0x2e ++#define RP1_DMA_ADC 0x2f ++#define RP1_DMA_DMA_TICK_TICK0 0x30 ++#define RP1_DMA_DMA_TICK_TICK1 0x31 ++#define RP1_DMA_SPI6_RX 0x32 ++#define RP1_DMA_SPI6_TX 0x33 ++#define RP1_DMA_SPI7_RX 0x34 ++#define RP1_DMA_SPI7_TX 0x35 ++#define RP1_DMA_SPI8_RX 0x36 ++#define RP1_DMA_SPI8_TX 0x37 ++#define RP1_DMA_PIO_CH0_TX 0x38 ++#define RP1_DMA_PIO_CH0_RX 0x39 ++#define RP1_DMA_PIO_CH1_TX 0x3a ++#define RP1_DMA_PIO_CH1_RX 0x3b ++#define RP1_DMA_PIO_CH2_TX 0x3c ++#define RP1_DMA_PIO_CH2_RX 0x3d ++#define RP1_DMA_PIO_CH3_TX 0x3e ++#define RP1_DMA_PIO_CH3_RX 0x3f ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-0872-mfd-Add-rp1-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0872-mfd-Add-rp1-driver.patch new file mode 100644 index 0000000000..dd252cba36 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0872-mfd-Add-rp1-driver.patch @@ -0,0 +1,442 @@ +From 7196a12b94e90225686e6c34cdf65a583214f7a5 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 10 Oct 2022 14:21:50 +0100 +Subject: [PATCH] mfd: Add rp1 driver + +RP1 is a multifunction PCIe device that exposes a range of +peripherals. +Add the parent driver to manage these. + +Signed-off-by: Phil Elwell +--- + drivers/mfd/Kconfig | 11 ++ + drivers/mfd/Makefile | 1 + + drivers/mfd/rp1.c | 367 +++++++++++++++++++++++++++++++++++ + include/linux/rp1_platform.h | 20 ++ + 4 files changed, 399 insertions(+) + create mode 100644 drivers/mfd/rp1.c + create mode 100644 include/linux/rp1_platform.h + +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -2252,6 +2252,17 @@ config MFD_INTEL_M10_BMC + additional drivers must be enabled in order to use the functionality + of the device. + ++config MFD_RP1 ++ tristate "RP1 MFD driver" ++ depends on PCI ++ select MFD_CORE ++ help ++ Support for the RP1 peripheral chip. ++ ++ This driver provides support for the Raspberry Pi RP1 peripheral chip. ++ It is responsible for enabling the Device Tree node once the PCIe endpoint ++ has been configured, and handling interrupts. ++ + config MFD_RSMU_I2C + tristate "Renesas Synchronization Management Unit with I2C" + depends on I2C && OF +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -273,6 +273,7 @@ obj-$(CONFIG_MFD_RPISENSE_CORE) += rpise + obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o + obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o + obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o ++obj-$(CONFIG_MFD_RP1) += rp1.o + + obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o + obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o +--- /dev/null ++++ b/drivers/mfd/rp1.c +@@ -0,0 +1,367 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2018-22 Raspberry Pi Ltd. ++ * All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* TO DO: ++ * 1. Occasional shutdown crash - RP1 being closed before its children? ++ * 2. DT mode interrupt handling. ++ */ ++ ++#define RP1_DRIVER_NAME "rp1" ++ ++#define PCI_VENDOR_ID_RPI 0x1de4 ++#define PCI_DEVICE_ID_RP1_C0 0x0001 ++#define PCI_DEVICE_REV_RP1_C0 2 ++ ++#define RP1_ACTUAL_IRQS RP1_INT_END ++#define RP1_IRQS RP1_ACTUAL_IRQS ++ ++#define RP1_SYSCLK_RATE 200000000 ++#define RP1_SYSCLK_FPGA_RATE 60000000 ++ ++// Don't want to include the whole sysinfo reg header ++#define SYSINFO_CHIP_ID_OFFSET 0x00000000 ++#define SYSINFO_PLATFORM_OFFSET 0x00000004 ++ ++#define REG_RW 0x000 ++#define REG_SET 0x800 ++#define REG_CLR 0xc00 ++ ++// MSIX CFG registers start at 0x8 ++#define MSIX_CFG(x) (0x8 + (4 * (x))) ++ ++#define MSIX_CFG_IACK_EN BIT(3) ++#define MSIX_CFG_IACK BIT(2) ++#define MSIX_CFG_TEST BIT(1) ++#define MSIX_CFG_ENABLE BIT(0) ++ ++#define INTSTATL 0x108 ++#define INTSTATH 0x10c ++ ++struct rp1_dev { ++ struct pci_dev *pdev; ++ struct device *dev; ++ resource_size_t bar_start; ++ resource_size_t bar_end; ++ struct clk *sys_clk; ++ struct irq_domain *domain; ++ struct irq_data *pcie_irqds[64]; ++ void __iomem *msix_cfg_regs; ++}; ++ ++static bool rp1_level_triggered_irq[RP1_ACTUAL_IRQS] = { 0 }; ++ ++static struct rp1_dev *g_rp1; ++static u32 g_chip_id, g_platform; ++ ++static void dump_bar(struct pci_dev *pdev, unsigned int bar) ++{ ++ dev_info(&pdev->dev, ++ "bar%d len 0x%llx, start 0x%llx, end 0x%llx, flags, 0x%lx\n", ++ bar, ++ pci_resource_len(pdev, bar), ++ pci_resource_start(pdev, bar), ++ pci_resource_end(pdev, bar), ++ pci_resource_flags(pdev, bar)); ++} ++ ++static void msix_cfg_set(struct rp1_dev *rp1, unsigned int hwirq, u32 value) ++{ ++ writel(value, rp1->msix_cfg_regs + REG_SET + MSIX_CFG(hwirq)); ++} ++ ++static void msix_cfg_clr(struct rp1_dev *rp1, unsigned int hwirq, u32 value) ++{ ++ writel(value, rp1->msix_cfg_regs + REG_CLR + MSIX_CFG(hwirq)); ++} ++ ++static void rp1_mask_irq(struct irq_data *irqd) ++{ ++ struct rp1_dev *rp1 = irqd->domain->host_data; ++ struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq]; ++ ++ pci_msi_mask_irq(pcie_irqd); ++} ++ ++static void rp1_unmask_irq(struct irq_data *irqd) ++{ ++ struct rp1_dev *rp1 = irqd->domain->host_data; ++ struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq]; ++ ++ pci_msi_unmask_irq(pcie_irqd); ++} ++ ++static int rp1_irq_set_type(struct irq_data *irqd, unsigned int type) ++{ ++ struct rp1_dev *rp1 = irqd->domain->host_data; ++ unsigned int hwirq = (unsigned int)irqd->hwirq; ++ int ret = 0; ++ ++ switch (type) { ++ case IRQ_TYPE_LEVEL_HIGH: ++ dev_dbg(rp1->dev, "MSIX IACK EN for irq %d\n", hwirq); ++ msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN); ++ rp1_level_triggered_irq[hwirq] = true; ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN); ++ rp1_level_triggered_irq[hwirq] = false; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static struct irq_chip rp1_irq_chip = { ++ .name = "rp1_irq_chip", ++ .irq_mask = rp1_mask_irq, ++ .irq_unmask = rp1_unmask_irq, ++ .irq_set_type = rp1_irq_set_type, ++}; ++ ++static void rp1_chained_handle_irq(struct irq_desc *desc) ++{ ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct rp1_dev *rp1 = desc->irq_data.chip_data; ++ unsigned int hwirq = desc->irq_data.hwirq & 0x3f; ++ int new_irq; ++ ++ rp1 = g_rp1; ++ ++ chained_irq_enter(chip, desc); ++ ++ new_irq = irq_linear_revmap(rp1->domain, hwirq); ++ generic_handle_irq(new_irq); ++ if (rp1_level_triggered_irq[hwirq]) ++ msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK); ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static int rp1_irq_xlate(struct irq_domain *d, struct device_node *node, ++ const u32 *intspec, unsigned int intsize, ++ unsigned long *out_hwirq, unsigned int *out_type) ++{ ++ struct rp1_dev *rp1 = d->host_data; ++ struct irq_data *pcie_irqd; ++ unsigned long hwirq; ++ int pcie_irq; ++ int ret; ++ ++ ret = irq_domain_xlate_twocell(d, node, intspec, intsize, ++ &hwirq, out_type); ++ if (!ret) { ++ pcie_irq = pci_irq_vector(rp1->pdev, hwirq); ++ pcie_irqd = irq_get_irq_data(pcie_irq); ++ rp1->pcie_irqds[hwirq] = pcie_irqd; ++ *out_hwirq = hwirq; ++ } ++ return ret; ++} ++ ++static int rp1_irq_activate(struct irq_domain *d, struct irq_data *irqd, ++ bool reserve) ++{ ++ struct rp1_dev *rp1 = d->host_data; ++ struct irq_data *pcie_irqd; ++ ++ pcie_irqd = rp1->pcie_irqds[irqd->hwirq]; ++ msix_cfg_set(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE); ++ return irq_domain_activate_irq(pcie_irqd, reserve); ++} ++ ++static void rp1_irq_deactivate(struct irq_domain *d, struct irq_data *irqd) ++{ ++ struct rp1_dev *rp1 = d->host_data; ++ struct irq_data *pcie_irqd; ++ ++ pcie_irqd = rp1->pcie_irqds[irqd->hwirq]; ++ msix_cfg_clr(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE); ++ return irq_domain_deactivate_irq(pcie_irqd); ++} ++ ++static const struct irq_domain_ops rp1_domain_ops = { ++ .xlate = rp1_irq_xlate, ++ .activate = rp1_irq_activate, ++ .deactivate = rp1_irq_deactivate, ++}; ++ ++static inline dma_addr_t rp1_io_to_phys(struct rp1_dev *rp1, unsigned int offset) ++{ ++ return rp1->bar_start + offset; ++} ++ ++static u32 rp1_reg_read(struct rp1_dev *rp1, unsigned int base_addr, u32 offset) ++{ ++ dma_addr_t phys = rp1_io_to_phys(rp1, base_addr); ++ void __iomem *regblock = ioremap(phys, 0x1000); ++ u32 value = readl(regblock + offset); ++ ++ iounmap(regblock); ++ return value; ++} ++ ++void rp1_get_platform(u32 *chip_id, u32 *platform) ++{ ++ if (chip_id) ++ *chip_id = g_chip_id; ++ if (platform) ++ *platform = g_platform; ++} ++EXPORT_SYMBOL_GPL(rp1_get_platform); ++ ++static int rp1_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++{ ++ struct reset_control *reset; ++ struct platform_device *pcie_pdev; ++ struct device_node *rp1_node; ++ struct rp1_dev *rp1; ++ int err = 0; ++ int i; ++ ++ reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); ++ if (IS_ERR(reset)) ++ return PTR_ERR(reset); ++ reset_control_reset(reset); ++ ++ dump_bar(pdev, 0); ++ dump_bar(pdev, 1); ++ ++ if (pci_resource_len(pdev, 1) <= 0x10000) { ++ dev_err(&pdev->dev, ++ "Not initialised - is the firmware running?\n"); ++ return -EINVAL; ++ } ++ ++ /* enable pci device */ ++ err = pcim_enable_device(pdev); ++ if (err < 0) { ++ dev_err(&pdev->dev, "Enabling PCI device has failed: %d", ++ err); ++ return err; ++ } ++ ++ pci_set_master(pdev); ++ ++ err = pci_alloc_irq_vectors(pdev, RP1_IRQS, RP1_IRQS, ++ PCI_IRQ_MSIX); ++ if (err != RP1_IRQS) { ++ dev_err(&pdev->dev, "pci_alloc_irq_vectors failed - %d\n", err); ++ return err; ++ } ++ ++ rp1 = devm_kzalloc(&pdev->dev, sizeof(*rp1), GFP_KERNEL); ++ if (!rp1) ++ return -ENOMEM; ++ ++ rp1->pdev = pdev; ++ rp1->dev = &pdev->dev; ++ ++ pci_set_drvdata(pdev, rp1); ++ ++ rp1->bar_start = pci_resource_start(pdev, 1); ++ rp1->bar_end = pci_resource_end(pdev, 1); ++ ++ // Get chip id ++ g_chip_id = rp1_reg_read(rp1, RP1_SYSINFO_BASE, SYSINFO_CHIP_ID_OFFSET); ++ g_platform = rp1_reg_read(rp1, RP1_SYSINFO_BASE, SYSINFO_PLATFORM_OFFSET); ++ dev_info(&pdev->dev, "chip_id 0x%x%s\n", g_chip_id, ++ (g_platform & RP1_PLATFORM_FPGA) ? " FPGA" : ""); ++ if (g_chip_id != RP1_C0_CHIP_ID) { ++ dev_err(&pdev->dev, "wrong chip id (%x)\n", g_chip_id); ++ return -EINVAL; ++ } ++ ++ rp1_node = of_find_node_by_name(NULL, "rp1"); ++ if (!rp1_node) { ++ dev_err(&pdev->dev, "failed to find RP1 DT node\n"); ++ return -EINVAL; ++ } ++ ++ pcie_pdev = of_find_device_by_node(rp1_node->parent); ++ rp1->domain = irq_domain_add_linear(rp1_node, RP1_IRQS, ++ &rp1_domain_ops, rp1); ++ ++ g_rp1 = rp1; ++ ++ /* TODO can this go in the rp1 device tree entry? */ ++ rp1->msix_cfg_regs = ioremap(rp1_io_to_phys(rp1, RP1_PCIE_APBS_BASE), 0x1000); ++ ++ for (i = 0; i < RP1_IRQS; i++) { ++ int irq = irq_create_mapping(rp1->domain, i); ++ ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to create irq mapping\n"); ++ return irq; ++ } ++ ++ irq_set_chip_data(irq, rp1); ++ irq_set_chip_and_handler(irq, &rp1_irq_chip, handle_level_irq); ++ irq_set_probe(irq); ++ irq_set_chained_handler(pci_irq_vector(pdev, i), ++ rp1_chained_handle_irq); ++ } ++ ++ if (rp1_node) ++ of_platform_populate(rp1_node, NULL, NULL, &pcie_pdev->dev); ++ ++ of_node_put(rp1_node); ++ ++ return 0; ++} ++ ++static void rp1_remove(struct pci_dev *pdev) ++{ ++ struct rp1_dev *rp1 = pci_get_drvdata(pdev); ++ ++ mfd_remove_devices(&pdev->dev); ++ ++ clk_unregister(rp1->sys_clk); ++} ++ ++static const struct pci_device_id dev_id_table[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RP1_C0), }, ++ { 0, } ++}; ++ ++static struct pci_driver rp1_driver = { ++ .name = RP1_DRIVER_NAME, ++ .id_table = dev_id_table, ++ .probe = rp1_probe, ++ .remove = rp1_remove, ++}; ++ ++module_pci_driver(rp1_driver); ++ ++MODULE_AUTHOR("Phil Elwell "); ++MODULE_DESCRIPTION("RP1 wrapper"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/include/linux/rp1_platform.h +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2021-2022 Raspberry Pi Ltd. ++ * All rights reserved. ++ */ ++ ++#ifndef _RP1_PLATFORM_H ++#define _RP1_PLATFORM_H ++ ++#include ++ ++#define RP1_B0_CHIP_ID 0x10001927 ++#define RP1_C0_CHIP_ID 0x20001927 ++ ++#define RP1_PLATFORM_ASIC BIT(1) ++#define RP1_PLATFORM_FPGA BIT(0) ++ ++void rp1_get_platform(u32 *chip_id, u32 *platform); ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch b/target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch new file mode 100644 index 0000000000..f94782438b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch @@ -0,0 +1,65 @@ +From 00ff2819eb852b54fe22e7181646e40d560576dc Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 28 Oct 2022 14:12:18 +0100 +Subject: [PATCH] dt-bindings: clock: Add bindings for Raspberry Pi RP1 + +Signed-off-by: Phil Elwell +--- + include/dt-bindings/clock/rp1.h | 51 +++++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + create mode 100644 include/dt-bindings/clock/rp1.h + +--- /dev/null ++++ b/include/dt-bindings/clock/rp1.h +@@ -0,0 +1,51 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2021 Raspberry Pi Ltd. ++ */ ++ ++#define RP1_PLL_SYS_CORE 0 ++#define RP1_PLL_AUDIO_CORE 1 ++#define RP1_PLL_VIDEO_CORE 2 ++ ++#define RP1_PLL_SYS 3 ++#define RP1_PLL_AUDIO 4 ++#define RP1_PLL_VIDEO 5 ++ ++#define RP1_PLL_SYS_PRI_PH 6 ++#define RP1_PLL_SYS_SEC_PH 7 ++ ++#define RP1_PLL_SYS_SEC 8 ++#define RP1_PLL_AUDIO_SEC 9 ++#define RP1_PLL_VIDEO_SEC 10 ++ ++#define RP1_CLK_SYS 11 ++#define RP1_CLK_SLOW_SYS 12 ++#define RP1_CLK_DMA 13 ++#define RP1_CLK_UART 14 ++#define RP1_CLK_ETH 15 ++#define RP1_CLK_PWM0 16 ++#define RP1_CLK_PWM1 17 ++#define RP1_CLK_AUDIO_IN 18 ++#define RP1_CLK_AUDIO_OUT 19 ++#define RP1_CLK_I2S 20 ++#define RP1_CLK_MIPI0_CFG 21 ++#define RP1_CLK_MIPI1_CFG 22 ++#define RP1_CLK_PCIE_AUX 23 ++#define RP1_CLK_USBH0_MICROFRAME 24 ++#define RP1_CLK_USBH1_MICROFRAME 25 ++#define RP1_CLK_USBH0_SUSPEND 26 ++#define RP1_CLK_USBH1_SUSPEND 27 ++#define RP1_CLK_ETH_TSU 28 ++#define RP1_CLK_ADC 29 ++#define RP1_CLK_SDIO_TIMER 30 ++#define RP1_CLK_SDIO_ALT_SRC 31 ++#define RP1_CLK_GP0 32 ++#define RP1_CLK_GP1 33 ++#define RP1_CLK_GP2 34 ++#define RP1_CLK_GP3 35 ++#define RP1_CLK_GP4 36 ++#define RP1_CLK_GP5 37 ++#define RP1_CLK_VEC 38 ++#define RP1_CLK_DPI 39 ++#define RP1_CLK_MIPI0_DPI 40 ++#define RP1_CLK_MIPI1_DPI 41 diff --git a/target/linux/bcm27xx/patches-6.1/950-0874-clk-Add-rp1-clock-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0874-clk-Add-rp1-clock-driver.patch new file mode 100644 index 0000000000..2a861d18c7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0874-clk-Add-rp1-clock-driver.patch @@ -0,0 +1,2208 @@ +From 66517cdfea750b89d86f78af55ef773cbd3e005f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 10 Oct 2022 14:25:38 +0100 +Subject: [PATCH] clk: Add rp1 clock driver + +RP1 contains various PLLs and clocks for driving the hardware +blocks, so add a driver to configure these. + +Signed-off-by: Phil Elwell +--- + drivers/clk/Kconfig | 7 + + drivers/clk/Makefile | 1 + + drivers/clk/clk-rp1.c | 2085 +++++++++++++++++++++++++++++++ + include/dt-bindings/clock/rp1.h | 69 +- + 4 files changed, 2128 insertions(+), 34 deletions(-) + create mode 100644 drivers/clk/clk-rp1.c + +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -89,6 +89,13 @@ config COMMON_CLK_RK808 + These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. + Clkout1 is always on, Clkout2 can off by control register. + ++config COMMON_CLK_RP1 ++ tristate "Raspberry Pi RP1-based clock support" ++ depends on PCI || COMPILE_TEST ++ depends on COMMON_CLK ++ help ++ Enable common clock framework support for Raspberry Pi RP1 ++ + config COMMON_CLK_HI655X + tristate "Clock driver for Hi655x" if EXPERT + depends on (MFD_HI655X_PMIC || COMPILE_TEST) +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -58,6 +58,7 @@ obj-$(CONFIG_CLK_LS1028A_PLLDIG) += clk- + obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o + obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o + obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o ++obj-$(CONFIG_COMMON_CLK_RP1) += clk-rp1.o + obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o + obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o + obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o +--- /dev/null ++++ b/drivers/clk/clk-rp1.c +@@ -0,0 +1,2085 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ * ++ * Clock driver for RP1 PCIe multifunction chip. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#define PLL_SYS_CS 0x08000 ++#define PLL_SYS_PWR 0x08004 ++#define PLL_SYS_FBDIV_INT 0x08008 ++#define PLL_SYS_FBDIV_FRAC 0x0800c ++#define PLL_SYS_PRIM 0x08010 ++#define PLL_SYS_SEC 0x08014 ++ ++#define PLL_AUDIO_CS 0x0c000 ++#define PLL_AUDIO_PWR 0x0c004 ++#define PLL_AUDIO_FBDIV_INT 0x0c008 ++#define PLL_AUDIO_FBDIV_FRAC 0x0c00c ++#define PLL_AUDIO_PRIM 0x0c010 ++#define PLL_AUDIO_SEC 0x0c014 ++ ++#define PLL_VIDEO_CS 0x10000 ++#define PLL_VIDEO_PWR 0x10004 ++#define PLL_VIDEO_FBDIV_INT 0x10008 ++#define PLL_VIDEO_FBDIV_FRAC 0x1000c ++#define PLL_VIDEO_PRIM 0x10010 ++#define PLL_VIDEO_SEC 0x10014 ++ ++#define CLK_SYS_CTRL 0x00014 ++#define CLK_SYS_DIV_INT 0x00018 ++#define CLK_SYS_SEL 0x00020 ++ ++#define CLK_SLOW_SYS_CTRL 0x00024 ++#define CLK_SLOW_SYS_DIV_INT 0x00028 ++#define CLK_SLOW_SYS_SEL 0x00030 ++ ++#define CLK_DMA_CTRL 0x00044 ++#define CLK_DMA_DIV_INT 0x00048 ++#define CLK_DMA_SEL 0x00050 ++ ++#define CLK_UART_CTRL 0x00054 ++#define CLK_UART_DIV_INT 0x00058 ++#define CLK_UART_SEL 0x00060 ++ ++#define CLK_ETH_CTRL 0x00064 ++#define CLK_ETH_DIV_INT 0x00068 ++#define CLK_ETH_SEL 0x00070 ++ ++#define CLK_PWM0_CTRL 0x00074 ++#define CLK_PWM0_DIV_INT 0x00078 ++#define CLK_PWM0_DIV_FRAC 0x0007c ++#define CLK_PWM0_SEL 0x00080 ++ ++#define CLK_PWM1_CTRL 0x00084 ++#define CLK_PWM1_DIV_INT 0x00088 ++#define CLK_PWM1_DIV_FRAC 0x0008c ++#define CLK_PWM1_SEL 0x00090 ++ ++#define CLK_AUDIO_IN_CTRL 0x00094 ++#define CLK_AUDIO_IN_DIV_INT 0x00098 ++#define CLK_AUDIO_IN_SEL 0x000a0 ++ ++#define CLK_AUDIO_OUT_CTRL 0x000a4 ++#define CLK_AUDIO_OUT_DIV_INT 0x000a8 ++#define CLK_AUDIO_OUT_SEL 0x000b0 ++ ++#define CLK_I2S_CTRL 0x000b4 ++#define CLK_I2S_DIV_INT 0x000b8 ++#define CLK_I2S_SEL 0x000c0 ++ ++#define CLK_MIPI0_CFG_CTRL 0x000c4 ++#define CLK_MIPI0_CFG_DIV_INT 0x000c8 ++#define CLK_MIPI0_CFG_SEL 0x000d0 ++ ++#define CLK_MIPI1_CFG_CTRL 0x000d4 ++#define CLK_MIPI1_CFG_DIV_INT 0x000d8 ++#define CLK_MIPI1_CFG_SEL 0x000e0 ++ ++#define CLK_PCIE_AUX_CTRL 0x000e4 ++#define CLK_PCIE_AUX_DIV_INT 0x000e8 ++#define CLK_PCIE_AUX_SEL 0x000f0 ++ ++#define CLK_USBH0_MICROFRAME_CTRL 0x000f4 ++#define CLK_USBH0_MICROFRAME_DIV_INT 0x000f8 ++#define CLK_USBH0_MICROFRAME_SEL 0x00100 ++ ++#define CLK_USBH1_MICROFRAME_CTRL 0x00104 ++#define CLK_USBH1_MICROFRAME_DIV_INT 0x00108 ++#define CLK_USBH1_MICROFRAME_SEL 0x00110 ++ ++#define CLK_USBH0_SUSPEND_CTRL 0x00114 ++#define CLK_USBH0_SUSPEND_DIV_INT 0x00118 ++#define CLK_USBH0_SUSPEND_SEL 0x00120 ++ ++#define CLK_USBH1_SUSPEND_CTRL 0x00124 ++#define CLK_USBH1_SUSPEND_DIV_INT 0x00128 ++#define CLK_USBH1_SUSPEND_SEL 0x00130 ++ ++#define CLK_ETH_TSU_CTRL 0x00134 ++#define CLK_ETH_TSU_DIV_INT 0x00138 ++#define CLK_ETH_TSU_SEL 0x00140 ++ ++#define CLK_ADC_CTRL 0x00144 ++#define CLK_ADC_DIV_INT 0x00148 ++#define CLK_ADC_SEL 0x00150 ++ ++#define CLK_SDIO_TIMER_CTRL 0x00154 ++#define CLK_SDIO_TIMER_DIV_INT 0x00158 ++#define CLK_SDIO_TIMER_SEL 0x00160 ++ ++#define CLK_SDIO_ALT_SRC_CTRL 0x00164 ++#define CLK_SDIO_ALT_SRC_DIV_INT 0x00168 ++#define CLK_SDIO_ALT_SRC_SEL 0x00170 ++ ++#define CLK_GP0_CTRL 0x00174 ++#define CLK_GP0_DIV_INT 0x00178 ++#define CLK_GP0_DIV_FRAC 0x0017c ++#define CLK_GP0_SEL 0x00180 ++ ++#define CLK_GP1_CTRL 0x00184 ++#define CLK_GP1_DIV_INT 0x00188 ++#define CLK_GP1_DIV_FRAC 0x0018c ++#define CLK_GP1_SEL 0x00190 ++ ++#define CLK_GP2_CTRL 0x00194 ++#define CLK_GP2_DIV_INT 0x00198 ++#define CLK_GP2_DIV_FRAC 0x0019c ++#define CLK_GP2_SEL 0x001a0 ++ ++#define CLK_GP3_CTRL 0x001a4 ++#define CLK_GP3_DIV_INT 0x001a8 ++#define CLK_GP3_DIV_FRAC 0x001ac ++#define CLK_GP3_SEL 0x001b0 ++ ++#define CLK_GP4_CTRL 0x001b4 ++#define CLK_GP4_DIV_INT 0x001b8 ++#define CLK_GP4_DIV_FRAC 0x001bc ++#define CLK_GP4_SEL 0x001c0 ++ ++#define CLK_GP5_CTRL 0x001c4 ++#define CLK_GP5_DIV_INT 0x001c8 ++#define CLK_GP5_DIV_FRAC 0x001cc ++#define CLK_GP5_SEL 0x001d0 ++ ++#define CLK_SYS_RESUS_CTRL 0x0020c ++ ++#define CLK_SLOW_SYS_RESUS_CTRL 0x00214 ++ ++#define FC0_REF_KHZ 0x0021c ++#define FC0_MIN_KHZ 0x00220 ++#define FC0_MAX_KHZ 0x00224 ++#define FC0_DELAY 0x00228 ++#define FC0_INTERVAL 0x0022c ++#define FC0_SRC 0x00230 ++#define FC0_STATUS 0x00234 ++#define FC0_RESULT 0x00238 ++#define FC_SIZE 0x20 ++#define FC_COUNT 8 ++#define FC_NUM(idx, off) ((idx) * 32 + (off)) ++ ++#define AUX_SEL 1 ++ ++#define VIDEO_CLOCKS_OFFSET 0x4000 ++#define VIDEO_CLK_VEC_CTRL (VIDEO_CLOCKS_OFFSET + 0x0000) ++#define VIDEO_CLK_VEC_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0004) ++#define VIDEO_CLK_VEC_SEL (VIDEO_CLOCKS_OFFSET + 0x000c) ++#define VIDEO_CLK_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0010) ++#define VIDEO_CLK_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0014) ++#define VIDEO_CLK_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x001c) ++#define VIDEO_CLK_MIPI0_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0020) ++#define VIDEO_CLK_MIPI0_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0024) ++#define VIDEO_CLK_MIPI0_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0028) ++#define VIDEO_CLK_MIPI0_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x002c) ++#define VIDEO_CLK_MIPI1_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0030) ++#define VIDEO_CLK_MIPI1_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0034) ++#define VIDEO_CLK_MIPI1_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0038) ++#define VIDEO_CLK_MIPI1_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x003c) ++ ++#define DIV_INT_8BIT_MAX 0x000000ffu /* max divide for most clocks */ ++#define DIV_INT_16BIT_MAX 0x0000ffffu /* max divide for GPx, PWM */ ++#define DIV_INT_24BIT_MAX 0x00ffffffu /* max divide for CLK_SYS */ ++ ++#define FC0_STATUS_DONE BIT(4) ++#define FC0_STATUS_RUNNING BIT(8) ++#define FC0_RESULT_FRAC_SHIFT 5 ++ ++#define PLL_PRIM_DIV1_SHIFT 16 ++#define PLL_PRIM_DIV1_MASK 0x00070000 ++#define PLL_PRIM_DIV2_SHIFT 12 ++#define PLL_PRIM_DIV2_MASK 0x00007000 ++ ++#define PLL_SEC_DIV_SHIFT 8 ++#define PLL_SEC_DIV_WIDTH 5 ++#define PLL_SEC_DIV_MASK 0x00001f00 ++ ++#define PLL_CS_LOCK BIT(31) ++#define PLL_CS_REFDIV_SHIFT 0 ++ ++#define PLL_PWR_PD BIT(0) ++#define PLL_PWR_DACPD BIT(1) ++#define PLL_PWR_DSMPD BIT(2) ++#define PLL_PWR_POSTDIVPD BIT(3) ++#define PLL_PWR_4PHASEPD BIT(4) ++#define PLL_PWR_VCOPD BIT(5) ++#define PLL_PWR_MASK 0x0000003f ++ ++#define PLL_SEC_RST BIT(16) ++#define PLL_SEC_IMPL BIT(31) ++ ++/* PLL phase output for both PRI and SEC */ ++#define PLL_PH_EN BIT(4) ++#define PLL_PH_PHASE_SHIFT 0 ++ ++#define RP1_PLL_PHASE_0 0 ++#define RP1_PLL_PHASE_90 1 ++#define RP1_PLL_PHASE_180 2 ++#define RP1_PLL_PHASE_270 3 ++ ++/* Clock fields for all clocks */ ++#define CLK_CTRL_ENABLE BIT(11) ++#define CLK_CTRL_AUXSRC_MASK 0x000003e0 ++#define CLK_CTRL_AUXSRC_SHIFT 5 ++#define CLK_CTRL_SRC_SHIFT 0 ++#define CLK_DIV_FRAC_BITS 16 ++ ++#define KHz 1000 ++#define MHz (KHz * KHz) ++#define LOCK_TIMEOUT_NS 100000000 ++#define FC_TIMEOUT_NS 100000000 ++ ++#define MAX_CLK_PARENTS 8 ++ ++#define MEASURE_CLOCK_RATE ++const char * const fc0_ref_clk_name = "clk_slow_sys"; ++ ++#define ABS_DIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) ++#define DIV_U64_NEAREST(a, b) div_u64(((a) + ((b) >> 1)), (b)) ++ ++/* ++ * Names of the reference clock for the pll cores. This name must match ++ * the DT reference clock-output-name. ++ */ ++static const char *const ref_clock = "xosc"; ++ ++/* ++ * Secondary PLL channel output divider table. ++ * Divider values range from 8 to 19. ++ * Invalid values default to 19 ++ */ ++static const struct clk_div_table pll_sec_div_table[] = { ++ { 0x00, 19 }, ++ { 0x01, 19 }, ++ { 0x02, 19 }, ++ { 0x03, 19 }, ++ { 0x04, 19 }, ++ { 0x05, 19 }, ++ { 0x06, 19 }, ++ { 0x07, 19 }, ++ { 0x08, 8 }, ++ { 0x09, 9 }, ++ { 0x0a, 10 }, ++ { 0x0b, 11 }, ++ { 0x0c, 12 }, ++ { 0x0d, 13 }, ++ { 0x0e, 14 }, ++ { 0x0f, 15 }, ++ { 0x10, 16 }, ++ { 0x11, 17 }, ++ { 0x12, 18 }, ++ { 0x13, 19 }, ++ { 0x14, 19 }, ++ { 0x15, 19 }, ++ { 0x16, 19 }, ++ { 0x17, 19 }, ++ { 0x18, 19 }, ++ { 0x19, 19 }, ++ { 0x1a, 19 }, ++ { 0x1b, 19 }, ++ { 0x1c, 19 }, ++ { 0x1d, 19 }, ++ { 0x1e, 19 }, ++ { 0x1f, 19 }, ++ { 0 } ++}; ++ ++struct rp1_clockman { ++ struct device *dev; ++ void __iomem *regs; ++ spinlock_t regs_lock; /* spinlock for all clocks */ ++ ++ /* Must be last */ ++ struct clk_hw_onecell_data onecell; ++}; ++ ++struct rp1_pll_core_data { ++ const char *name; ++ u32 cs_reg; ++ u32 pwr_reg; ++ u32 fbdiv_int_reg; ++ u32 fbdiv_frac_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_data { ++ const char *name; ++ const char *source_pll; ++ u32 ctrl_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_ph_data { ++ const char *name; ++ const char *source_pll; ++ unsigned int phase; ++ unsigned int fixed_divider; ++ u32 ph_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_divider_data { ++ const char *name; ++ const char *source_pll; ++ u32 sec_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_clock_data { ++ const char *name; ++ const char *const parents[MAX_CLK_PARENTS]; ++ int num_std_parents; ++ int num_aux_parents; ++ unsigned long flags; ++ u32 clk_src_mask; ++ u32 ctrl_reg; ++ u32 div_int_reg; ++ u32 div_frac_reg; ++ u32 sel_reg; ++ u32 div_int_max; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_core { ++ struct clk_hw hw; ++ struct rp1_clockman *clockman; ++ const struct rp1_pll_core_data *data; ++ unsigned long cached_rate; ++}; ++ ++struct rp1_pll { ++ struct clk_hw hw; ++ struct clk_divider div; ++ struct rp1_clockman *clockman; ++ const struct rp1_pll_data *data; ++ unsigned long cached_rate; ++}; ++ ++struct rp1_pll_ph { ++ struct clk_hw hw; ++ struct rp1_clockman *clockman; ++ const struct rp1_pll_ph_data *data; ++}; ++ ++struct rp1_clock { ++ struct clk_hw hw; ++ struct rp1_clockman *clockman; ++ const struct rp1_clock_data *data; ++ unsigned long cached_rate; ++}; ++ ++static void rp1_debugfs_regset(struct rp1_clockman *clockman, u32 base, ++ const struct debugfs_reg32 *regs, ++ size_t nregs, struct dentry *dentry) ++{ ++ struct debugfs_regset32 *regset; ++ ++ regset = devm_kzalloc(clockman->dev, sizeof(*regset), GFP_KERNEL); ++ if (!regset) ++ return; ++ ++ regset->regs = regs; ++ regset->nregs = nregs; ++ regset->base = clockman->regs + base; ++ ++ debugfs_create_regset32("regdump", 0444, dentry, regset); ++} ++ ++static inline u32 set_register_field(u32 reg, u32 val, u32 mask, u32 shift) ++{ ++ reg &= ~mask; ++ reg |= (val << shift) & mask; ++ return reg; ++} ++ ++static inline ++void clockman_write(struct rp1_clockman *clockman, u32 reg, u32 val) ++{ ++ writel(val, clockman->regs + reg); ++} ++ ++static inline u32 clockman_read(struct rp1_clockman *clockman, u32 reg) ++{ ++ return readl(clockman->regs + reg); ++} ++ ++#ifdef MEASURE_CLOCK_RATE ++static unsigned long clockman_measure_clock(struct rp1_clockman *clockman, ++ const char *clk_name, ++ unsigned int fc0_src) ++{ ++ struct clk *ref_clk = __clk_lookup(fc0_ref_clk_name); ++ unsigned long result; ++ ktime_t timeout; ++ unsigned int fc_idx, fc_offset, fc_src; ++ ++ fc_idx = fc0_src / 32; ++ fc_src = fc0_src % 32; ++ ++ /* fc_src == 0 is invalid. */ ++ if (!fc_src || fc_idx >= FC_COUNT) ++ return 0; ++ ++ fc_offset = fc_idx * FC_SIZE; ++ ++ /* Ensure the frequency counter is idle. */ ++ timeout = ktime_add_ns(ktime_get(), FC_TIMEOUT_NS); ++ while (clockman_read(clockman, fc_offset + FC0_STATUS) & FC0_STATUS_RUNNING) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(clockman->dev, "%s: FC0 busy timeout\n", ++ clk_name); ++ return 0; ++ } ++ cpu_relax(); ++ } ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, fc_offset + FC0_REF_KHZ, ++ clk_get_rate(ref_clk) / KHz); ++ clockman_write(clockman, fc_offset + FC0_MIN_KHZ, 0); ++ clockman_write(clockman, fc_offset + FC0_MAX_KHZ, 0x1ffffff); ++ clockman_write(clockman, fc_offset + FC0_INTERVAL, 8); ++ clockman_write(clockman, fc_offset + FC0_DELAY, 7); ++ clockman_write(clockman, fc_offset + FC0_SRC, fc_src); ++ spin_unlock(&clockman->regs_lock); ++ ++ /* Ensure the frequency counter is idle. */ ++ timeout = ktime_add_ns(ktime_get(), FC_TIMEOUT_NS); ++ while (!(clockman_read(clockman, fc_offset + FC0_STATUS) & FC0_STATUS_DONE)) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(clockman->dev, "%s: FC0 wait timeout\n", ++ clk_name); ++ return 0; ++ } ++ cpu_relax(); ++ } ++ ++ result = clockman_read(clockman, fc_offset + FC0_RESULT); ++ ++ /* Disable FC0 */ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, fc_offset + FC0_SRC, 0); ++ spin_unlock(&clockman->regs_lock); ++ ++ return result; ++} ++#endif ++ ++static int rp1_pll_core_is_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ u32 pwr = clockman_read(clockman, data->pwr_reg); ++ ++ return (pwr & PLL_PWR_PD) || (pwr & PLL_PWR_POSTDIVPD); ++} ++ ++static int rp1_pll_core_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ u32 fbdiv_frac; ++ ktime_t timeout; ++ ++ spin_lock(&clockman->regs_lock); ++ ++ if (!(clockman_read(clockman, data->cs_reg) & PLL_CS_LOCK)) { ++ /* Reset to a known state. */ ++ clockman_write(clockman, data->pwr_reg, PLL_PWR_MASK); ++ clockman_write(clockman, data->fbdiv_int_reg, 20); ++ clockman_write(clockman, data->fbdiv_frac_reg, 0); ++ clockman_write(clockman, data->cs_reg, 1 << PLL_CS_REFDIV_SHIFT); ++ } ++ ++ /* Come out of reset. */ ++ fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg); ++ clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD); ++ spin_unlock(&clockman->regs_lock); ++ ++ /* Wait for the PLL to lock. */ ++ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS); ++ while (!(clockman_read(clockman, data->cs_reg) & PLL_CS_LOCK)) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(clockman->dev, "%s: can't lock PLL\n", ++ clk_hw_get_name(hw)); ++ return -ETIMEDOUT; ++ } ++ cpu_relax(); ++ } ++ ++ return 0; ++} ++ ++static void rp1_pll_core_off(struct clk_hw *hw) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->pwr_reg, 0); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static inline unsigned long get_pll_core_divider(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate, ++ u32 *div_int, u32 *div_frac) ++{ ++ unsigned long calc_rate; ++ u32 fbdiv_int, fbdiv_frac; ++ u64 div_fp64; /* 32.32 fixed point fraction. */ ++ ++ /* Factor of reference clock to VCO frequency. */ ++ div_fp64 = (u64)(rate) << 32; ++ div_fp64 = DIV_U64_NEAREST(div_fp64, parent_rate); ++ ++ /* Round the fractional component at 24 bits. */ ++ div_fp64 += 1 << (32 - 24 - 1); ++ ++ fbdiv_int = div_fp64 >> 32; ++ fbdiv_frac = (div_fp64 >> (32 - 24)) & 0xffffff; ++ ++ calc_rate = ++ ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; ++ ++ *div_int = fbdiv_int; ++ *div_frac = fbdiv_frac; ++ ++ return calc_rate; ++} ++ ++static int rp1_pll_core_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ unsigned long calc_rate; ++ u32 fbdiv_int, fbdiv_frac; ++ ++ // todo: is this needed?? ++ //rp1_pll_off(hw); ++ ++ /* Disable dividers to start with. */ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->fbdiv_int_reg, 0); ++ clockman_write(clockman, data->fbdiv_frac_reg, 0); ++ spin_unlock(&clockman->regs_lock); ++ ++ calc_rate = get_pll_core_divider(hw, rate, parent_rate, ++ &fbdiv_int, &fbdiv_frac); ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD); ++ clockman_write(clockman, data->fbdiv_int_reg, fbdiv_int); ++ clockman_write(clockman, data->fbdiv_frac_reg, fbdiv_frac); ++ spin_unlock(&clockman->regs_lock); ++ ++ /* Check that reference frequency is no greater than VCO / 16. */ ++ BUG_ON(parent_rate > (rate / 16)); ++ ++ pll_core->cached_rate = calc_rate; ++ ++ spin_lock(&clockman->regs_lock); ++ /* Don't need to divide ref unless parent_rate > (output freq / 16) */ ++ clockman_write(clockman, data->cs_reg, ++ clockman_read(clockman, data->cs_reg) | ++ (1 << PLL_CS_REFDIV_SHIFT)); ++ spin_unlock(&clockman->regs_lock); ++ ++ return 0; ++} ++ ++static unsigned long rp1_pll_core_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ u32 fbdiv_int, fbdiv_frac; ++ unsigned long calc_rate; ++ ++ fbdiv_int = clockman_read(clockman, data->fbdiv_int_reg); ++ fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg); ++ calc_rate = ++ ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; ++ ++ return calc_rate; ++} ++ ++static long rp1_pll_core_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ u32 fbdiv_int, fbdiv_frac; ++ long calc_rate; ++ ++ calc_rate = get_pll_core_divider(hw, rate, *parent_rate, ++ &fbdiv_int, &fbdiv_frac); ++ return calc_rate; ++} ++ ++static void rp1_pll_core_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 4, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "cs"; ++ regs[0].offset = data->cs_reg; ++ regs[1].name = "pwr"; ++ regs[1].offset = data->pwr_reg; ++ regs[2].name = "fbdiv_int"; ++ regs[2].offset = data->fbdiv_int_reg; ++ regs[3].name = "fbdiv_frac"; ++ regs[3].offset = data->fbdiv_frac_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 4, dentry); ++} ++ ++static void get_pll_prim_dividers(unsigned long rate, unsigned long parent_rate, ++ u32 *divider1, u32 *divider2) ++{ ++ unsigned int div1, div2; ++ unsigned int best_div1 = 7, best_div2 = 7; ++ unsigned long best_rate_diff = ++ ABS_DIFF(DIV_ROUND_CLOSEST(parent_rate, best_div1 * best_div2), rate); ++ long rate_diff, calc_rate; ++ ++ for (div1 = 1; div1 <= 7; div1++) { ++ for (div2 = 1; div2 <= div1; div2++) { ++ calc_rate = DIV_ROUND_CLOSEST(parent_rate, div1 * div2); ++ rate_diff = ABS_DIFF(calc_rate, rate); ++ ++ if (calc_rate == rate) { ++ best_div1 = div1; ++ best_div2 = div2; ++ goto done; ++ } else if (rate_diff < best_rate_diff) { ++ best_div1 = div1; ++ best_div2 = div2; ++ best_rate_diff = rate_diff; ++ } ++ } ++ } ++ ++done: ++ *divider1 = best_div1; ++ *divider2 = best_div2; ++} ++ ++static int rp1_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_data *data = pll->data; ++ u32 prim, prim_div1, prim_div2; ++ ++ get_pll_prim_dividers(rate, parent_rate, &prim_div1, &prim_div2); ++ ++ spin_lock(&clockman->regs_lock); ++ prim = clockman_read(clockman, data->ctrl_reg); ++ prim = set_register_field(prim, prim_div1, PLL_PRIM_DIV1_MASK, ++ PLL_PRIM_DIV1_SHIFT); ++ prim = set_register_field(prim, prim_div2, PLL_PRIM_DIV2_MASK, ++ PLL_PRIM_DIV2_SHIFT); ++ clockman_write(clockman, data->ctrl_reg, prim); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static unsigned long rp1_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_data *data = pll->data; ++ u32 prim, prim_div1, prim_div2; ++ ++ prim = clockman_read(clockman, data->ctrl_reg); ++ prim_div1 = (prim & PLL_PRIM_DIV1_MASK) >> PLL_PRIM_DIV1_SHIFT; ++ prim_div2 = (prim & PLL_PRIM_DIV2_MASK) >> PLL_PRIM_DIV2_SHIFT; ++ ++ if (!prim_div1 || !prim_div2) { ++ dev_err(clockman->dev, "%s: (%s) zero divider value\n", ++ __func__, data->name); ++ return 0; ++ } ++ ++ return DIV_ROUND_CLOSEST(parent_rate, prim_div1 * prim_div2); ++} ++ ++static long rp1_pll_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ u32 div1, div2; ++ ++ get_pll_prim_dividers(rate, *parent_rate, &div1, &div2); ++ ++ return DIV_ROUND_CLOSEST(*parent_rate, div1 * div2); ++} ++ ++static void rp1_pll_debug_init(struct clk_hw *hw, ++ struct dentry *dentry) ++{ ++ struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_data *data = pll->data; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "prim"; ++ regs[0].offset = data->ctrl_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 1, dentry); ++} ++ ++static int rp1_pll_ph_is_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_ph *pll = container_of(hw, struct rp1_pll_ph, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_ph_data *data = pll->data; ++ ++ return !!(clockman_read(clockman, data->ph_reg) & PLL_PH_EN); ++} ++ ++static int rp1_pll_ph_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ u32 ph_reg; ++ ++ /* todo: ensure pri/sec is enabled! */ ++ spin_lock(&clockman->regs_lock); ++ ph_reg = clockman_read(clockman, data->ph_reg); ++ ph_reg |= data->phase << PLL_PH_PHASE_SHIFT; ++ ph_reg |= PLL_PH_EN; ++ clockman_write(clockman, data->ph_reg, ph_reg); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static void rp1_pll_ph_off(struct clk_hw *hw) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ph_reg, ++ clockman_read(clockman, data->ph_reg) & ~PLL_PH_EN); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static int rp1_pll_ph_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ ++ /* Nothing really to do here! */ ++ WARN_ON(data->fixed_divider != 1 && data->fixed_divider != 2); ++ WARN_ON(rate != parent_rate / data->fixed_divider); ++ ++#ifdef MEASURE_CLOCK_RATE ++ if (rp1_pll_ph_is_on(hw)) ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static unsigned long rp1_pll_ph_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ ++ return parent_rate / data->fixed_divider; ++} ++ ++static long rp1_pll_ph_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ ++ return *parent_rate / data->fixed_divider; ++} ++ ++static void rp1_pll_ph_debug_init(struct clk_hw *hw, ++ struct dentry *dentry) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "ph_reg"; ++ regs[0].offset = data->ph_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 1, dentry); ++} ++ ++static int rp1_pll_divider_is_on(struct clk_hw *hw) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ ++ return !(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_RST); ++} ++ ++static int rp1_pll_divider_on(struct clk_hw *hw) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ ++ spin_lock(&clockman->regs_lock); ++ /* Check the implementation bit is set! */ ++ WARN_ON(!(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_IMPL)); ++ clockman_write(clockman, data->ctrl_reg, ++ clockman_read(clockman, data->ctrl_reg) & ~PLL_SEC_RST); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static void rp1_pll_divider_off(struct clk_hw *hw) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ctrl_reg, PLL_SEC_RST); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static int rp1_pll_divider_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ u32 div, sec; ++ ++ div = DIV_ROUND_UP_ULL(parent_rate, rate); ++ div = clamp(div, 8u, 19u); ++ ++ spin_lock(&clockman->regs_lock); ++ sec = clockman_read(clockman, data->ctrl_reg); ++ sec = set_register_field(sec, div, PLL_SEC_DIV_MASK, PLL_SEC_DIV_SHIFT); ++ ++ /* Must keep the divider in reset to change the value. */ ++ sec |= PLL_SEC_RST; ++ clockman_write(clockman, data->ctrl_reg, sec); ++ ++ // todo: must sleep 10 pll vco cycles ++ sec &= ~PLL_SEC_RST; ++ clockman_write(clockman, data->ctrl_reg, sec); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ if (rp1_pll_divider_is_on(hw)) ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static unsigned long rp1_pll_divider_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ return clk_divider_ops.recalc_rate(hw, parent_rate); ++} ++ ++static long rp1_pll_divider_round_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ return clk_divider_ops.round_rate(hw, rate, parent_rate); ++} ++ ++static void rp1_pll_divider_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "sec"; ++ regs[0].offset = data->ctrl_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 1, dentry); ++} ++ ++static int rp1_clock_is_on(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ ++ return !!(clockman_read(clockman, data->ctrl_reg) & CLK_CTRL_ENABLE); ++} ++ ++static unsigned long rp1_clock_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u64 calc_rate; ++ u64 div; ++ ++ u32 frac; ++ ++ div = clockman_read(clockman, data->div_int_reg); ++ frac = (data->div_frac_reg != 0) ? ++ clockman_read(clockman, data->div_frac_reg) : 0; ++ ++ /* If the integer portion of the divider is 0, treat it as 2^16 */ ++ if (!div) ++ div = 1 << 16; ++ ++ div = (div << CLK_DIV_FRAC_BITS) | (frac >> (32 - CLK_DIV_FRAC_BITS)); ++ ++ calc_rate = (u64)parent_rate << CLK_DIV_FRAC_BITS; ++ calc_rate = div64_u64(calc_rate, div); ++ ++ return calc_rate; ++} ++ ++static int rp1_clock_on(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ctrl_reg, ++ clockman_read(clockman, data->ctrl_reg) | CLK_CTRL_ENABLE); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static void rp1_clock_off(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ctrl_reg, ++ clockman_read(clockman, data->ctrl_reg) & ~CLK_CTRL_ENABLE); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static u32 rp1_clock_choose_div(unsigned long rate, unsigned long parent_rate, ++ const struct rp1_clock_data *data) ++{ ++ u64 div; ++ ++ /* ++ * Due to earlier rounding, calculated parent_rate may differ from ++ * expected value. Don't fail on a small discrepancy near unity divide. ++ */ ++ if (!rate || rate > parent_rate + (parent_rate >> CLK_DIV_FRAC_BITS)) ++ return 0; ++ ++ /* ++ * Always express div in fixed-point format for fractional division; ++ * If no fractional divider is present, the fraction part will be zero. ++ */ ++ if (data->div_frac_reg) { ++ div = (u64)parent_rate << CLK_DIV_FRAC_BITS; ++ div = DIV_U64_NEAREST(div, rate); ++ } else { ++ div = DIV_U64_NEAREST(parent_rate, rate); ++ div <<= CLK_DIV_FRAC_BITS; ++ } ++ ++ div = clamp(div, ++ 1ull << CLK_DIV_FRAC_BITS, ++ (u64)data->div_int_max << CLK_DIV_FRAC_BITS); ++ ++ return div; ++} ++ ++static u8 rp1_clock_get_parent(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u32 sel, ctrl; ++ u8 parent; ++ ++ /* Sel is one-hot, so find the first bit set */ ++ sel = clockman_read(clockman, data->sel_reg); ++ parent = ffs(sel) - 1; ++ ++ /* sel == 0 implies the parent clock is not enabled yet. */ ++ if (!sel) { ++ /* Read the clock src from the CTRL register instead */ ++ ctrl = clockman_read(clockman, data->ctrl_reg); ++ parent = (ctrl & data->clk_src_mask) >> CLK_CTRL_SRC_SHIFT; ++ } ++ ++ if (parent >= data->num_std_parents) ++ parent = AUX_SEL; ++ ++ if (parent == AUX_SEL) { ++ /* ++ * Clock parent is an auxiliary source, so get the parent from ++ * the AUXSRC register field. ++ */ ++ ctrl = clockman_read(clockman, data->ctrl_reg); ++ parent = (ctrl & CLK_CTRL_AUXSRC_MASK) >> CLK_CTRL_AUXSRC_SHIFT; ++ parent += data->num_std_parents; ++ } ++ ++ return parent; ++} ++ ++static int rp1_clock_set_parent(struct clk_hw *hw, u8 index) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u32 ctrl, sel; ++ ++ spin_lock(&clockman->regs_lock); ++ ctrl = clockman_read(clockman, data->ctrl_reg); ++ ++ if (index >= data->num_std_parents) { ++ /* This is an aux source request */ ++ if (index >= data->num_std_parents + data->num_aux_parents) ++ return -EINVAL; ++ ++ /* Select parent from aux list */ ++ ctrl = set_register_field(ctrl, index - data->num_std_parents, ++ CLK_CTRL_AUXSRC_MASK, ++ CLK_CTRL_AUXSRC_SHIFT); ++ /* Set src to aux list */ ++ ctrl = set_register_field(ctrl, AUX_SEL, data->clk_src_mask, ++ CLK_CTRL_SRC_SHIFT); ++ } else { ++ ctrl = set_register_field(ctrl, index, data->clk_src_mask, ++ CLK_CTRL_SRC_SHIFT); ++ } ++ ++ clockman_write(clockman, data->ctrl_reg, ctrl); ++ spin_unlock(&clockman->regs_lock); ++ ++ sel = rp1_clock_get_parent(hw); ++ WARN(sel != index, "(%s): Parent index req %u returned back %u\n", ++ data->name, index, sel); ++ ++ return 0; ++} ++ ++static int rp1_clock_set_rate_and_parent(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate, ++ u8 parent) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u32 div = rp1_clock_choose_div(rate, parent_rate, data); ++ ++ WARN(rate > 4000000000ll, "rate is -ve (%d)\n", (int)rate); ++ ++ if (WARN(!div, ++ "clk divider calculated as 0! (%s, rate %ld, parent rate %ld)\n", ++ data->name, rate, parent_rate)) ++ div = 1 << CLK_DIV_FRAC_BITS; ++ ++ spin_lock(&clockman->regs_lock); ++ ++ clockman_write(clockman, data->div_int_reg, div >> CLK_DIV_FRAC_BITS); ++ if (data->div_frac_reg) ++ clockman_write(clockman, data->div_frac_reg, div << (32 - CLK_DIV_FRAC_BITS)); ++ ++ spin_unlock(&clockman->regs_lock); ++ ++ if (parent != 0xff) ++ rp1_clock_set_parent(hw, parent); ++ ++#ifdef MEASURE_CLOCK_RATE ++ if (rp1_clock_is_on(hw)) ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static int rp1_clock_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ return rp1_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff); ++} ++ ++static void rp1_clock_choose_div_and_prate(struct clk_hw *hw, ++ int parent_idx, ++ unsigned long rate, ++ unsigned long *prate, ++ unsigned long *calc_rate) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ const struct rp1_clock_data *data = clock->data; ++ struct clk_hw *parent; ++ u32 div; ++ u64 tmp; ++ ++ parent = clk_hw_get_parent_by_index(hw, parent_idx); ++ *prate = clk_hw_get_rate(parent); ++ div = rp1_clock_choose_div(rate, *prate, data); ++ ++ if (!div) { ++ *calc_rate = 0; ++ return; ++ } ++ ++ /* Recalculate to account for rounding errors */ ++ tmp = (u64)*prate << CLK_DIV_FRAC_BITS; ++ tmp = div_u64(tmp, div); ++ *calc_rate = tmp; ++} ++ ++static int rp1_clock_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ struct clk_hw *parent, *best_parent = NULL; ++ unsigned long best_rate = 0; ++ unsigned long best_prate = 0; ++ unsigned long best_rate_diff = ULONG_MAX; ++ unsigned long prate, calc_rate; ++ size_t i; ++ ++ /* ++ * If the NO_REPARENT flag is set, try to use existing parent. ++ */ ++ if ((clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT)) { ++ i = rp1_clock_get_parent(hw); ++ parent = clk_hw_get_parent_by_index(hw, i); ++ if (parent) { ++ rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate, ++ &calc_rate); ++ if (calc_rate > 0) { ++ req->best_parent_hw = parent; ++ req->best_parent_rate = prate; ++ req->rate = calc_rate; ++ return 0; ++ } ++ } ++ } ++ ++ /* ++ * Select parent clock that results in the closest rate (lower or ++ * higher) ++ */ ++ for (i = 0; i < clk_hw_get_num_parents(hw); i++) { ++ parent = clk_hw_get_parent_by_index(hw, i); ++ if (!parent) ++ continue; ++ ++ rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate, ++ &calc_rate); ++ ++ if (ABS_DIFF(calc_rate, req->rate) < best_rate_diff) { ++ best_parent = parent; ++ best_prate = prate; ++ best_rate = calc_rate; ++ best_rate_diff = ABS_DIFF(calc_rate, req->rate); ++ ++ if (best_rate_diff == 0) ++ break; ++ } ++ } ++ ++ if (best_rate == 0) ++ return -EINVAL; ++ ++ req->best_parent_hw = best_parent; ++ req->best_parent_rate = best_prate; ++ req->rate = best_rate; ++ ++ return 0; ++} ++ ++static void rp1_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ struct debugfs_reg32 *regs; ++ int i; ++ ++ regs = devm_kcalloc(clockman->dev, 4, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ i = 0; ++ regs[i].name = "ctrl"; ++ regs[i++].offset = data->ctrl_reg; ++ regs[i].name = "div_int"; ++ regs[i++].offset = data->div_int_reg; ++ regs[i].name = "div_frac"; ++ regs[i++].offset = data->div_frac_reg; ++ regs[i].name = "sel"; ++ regs[i++].offset = data->sel_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, i, dentry); ++} ++ ++static const struct clk_ops rp1_pll_core_ops = { ++ .is_prepared = rp1_pll_core_is_on, ++ .prepare = rp1_pll_core_on, ++ .unprepare = rp1_pll_core_off, ++ .set_rate = rp1_pll_core_set_rate, ++ .recalc_rate = rp1_pll_core_recalc_rate, ++ .round_rate = rp1_pll_core_round_rate, ++ .debug_init = rp1_pll_core_debug_init, ++}; ++ ++static const struct clk_ops rp1_pll_ops = { ++ .set_rate = rp1_pll_set_rate, ++ .recalc_rate = rp1_pll_recalc_rate, ++ .round_rate = rp1_pll_round_rate, ++ .debug_init = rp1_pll_debug_init, ++}; ++ ++static const struct clk_ops rp1_pll_ph_ops = { ++ .is_prepared = rp1_pll_ph_is_on, ++ .prepare = rp1_pll_ph_on, ++ .unprepare = rp1_pll_ph_off, ++ .set_rate = rp1_pll_ph_set_rate, ++ .recalc_rate = rp1_pll_ph_recalc_rate, ++ .round_rate = rp1_pll_ph_round_rate, ++ .debug_init = rp1_pll_ph_debug_init, ++}; ++ ++static const struct clk_ops rp1_pll_divider_ops = { ++ .is_prepared = rp1_pll_divider_is_on, ++ .prepare = rp1_pll_divider_on, ++ .unprepare = rp1_pll_divider_off, ++ .set_rate = rp1_pll_divider_set_rate, ++ .recalc_rate = rp1_pll_divider_recalc_rate, ++ .round_rate = rp1_pll_divider_round_rate, ++ .debug_init = rp1_pll_divider_debug_init, ++}; ++ ++static const struct clk_ops rp1_clk_ops = { ++ .is_prepared = rp1_clock_is_on, ++ .prepare = rp1_clock_on, ++ .unprepare = rp1_clock_off, ++ .recalc_rate = rp1_clock_recalc_rate, ++ .get_parent = rp1_clock_get_parent, ++ .set_parent = rp1_clock_set_parent, ++ .set_rate_and_parent = rp1_clock_set_rate_and_parent, ++ .set_rate = rp1_clock_set_rate, ++ .determine_rate = rp1_clock_determine_rate, ++ .debug_init = rp1_clk_debug_init, ++}; ++ ++static bool rp1_clk_is_claimed(const char *name); ++ ++static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_core_data *pll_core_data = data; ++ struct rp1_pll_core *pll_core; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ /* All of the PLL cores derive from the external oscillator. */ ++ init.parent_names = &ref_clock; ++ init.num_parents = 1; ++ init.name = pll_core_data->name; ++ init.ops = &rp1_pll_core_ops; ++ init.flags = pll_core_data->flags | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL; ++ ++ pll_core = kzalloc(sizeof(*pll_core), GFP_KERNEL); ++ if (!pll_core) ++ return NULL; ++ ++ pll_core->clockman = clockman; ++ pll_core->data = pll_core_data; ++ pll_core->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &pll_core->hw); ++ if (ret) { ++ kfree(pll_core); ++ return NULL; ++ } ++ ++ return &pll_core->hw; ++} ++ ++static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_data *pll_data = data; ++ struct rp1_pll *pll; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ init.parent_names = &pll_data->source_pll; ++ init.num_parents = 1; ++ init.name = pll_data->name; ++ init.ops = &rp1_pll_ops; ++ init.flags = pll_data->flags | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL; ++ ++ pll = kzalloc(sizeof(*pll), GFP_KERNEL); ++ if (!pll) ++ return NULL; ++ ++ pll->clockman = clockman; ++ pll->data = pll_data; ++ pll->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &pll->hw); ++ if (ret) { ++ kfree(pll); ++ return NULL; ++ } ++ ++ return &pll->hw; ++} ++ ++static struct clk_hw *rp1_register_pll_ph(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_ph_data *ph_data = data; ++ struct rp1_pll_ph *ph; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ /* All of the PLLs derive from the external oscillator. */ ++ init.parent_names = &ph_data->source_pll; ++ init.num_parents = 1; ++ init.name = ph_data->name; ++ init.ops = &rp1_pll_ph_ops; ++ init.flags = ph_data->flags | CLK_IGNORE_UNUSED; ++ ++ ph = kzalloc(sizeof(*ph), GFP_KERNEL); ++ if (!ph) ++ return NULL; ++ ++ ph->clockman = clockman; ++ ph->data = ph_data; ++ ph->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &ph->hw); ++ if (ret) { ++ kfree(ph); ++ return NULL; ++ } ++ ++ return &ph->hw; ++} ++ ++static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_data *divider_data = data; ++ struct rp1_pll *divider; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ init.parent_names = ÷r_data->source_pll; ++ init.num_parents = 1; ++ init.name = divider_data->name; ++ init.ops = &rp1_pll_divider_ops; ++ init.flags = divider_data->flags | CLK_IGNORE_UNUSED; ++ ++ divider = devm_kzalloc(clockman->dev, sizeof(*divider), GFP_KERNEL); ++ if (!divider) ++ return NULL; ++ ++ divider->div.reg = clockman->regs + divider_data->ctrl_reg; ++ divider->div.shift = PLL_SEC_DIV_SHIFT; ++ divider->div.width = PLL_SEC_DIV_WIDTH; ++ divider->div.flags = CLK_DIVIDER_ROUND_CLOSEST; ++ divider->div.lock = &clockman->regs_lock; ++ divider->div.hw.init = &init; ++ divider->div.table = pll_sec_div_table; ++ ++ if (!rp1_clk_is_claimed(divider_data->source_pll)) ++ init.flags |= CLK_IS_CRITICAL; ++ if (!rp1_clk_is_claimed(divider_data->name)) ++ divider->div.flags |= CLK_IS_CRITICAL; ++ ++ divider->clockman = clockman; ++ divider->data = divider_data; ++ ++ ret = devm_clk_hw_register(clockman->dev, ÷r->div.hw); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ return ÷r->div.hw; ++} ++ ++static struct clk_hw *rp1_register_clock(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_clock_data *clock_data = data; ++ struct rp1_clock *clock; ++ struct clk_init_data init; ++ int ret; ++ ++ BUG_ON(MAX_CLK_PARENTS < ++ clock_data->num_std_parents + clock_data->num_aux_parents); ++ /* There must be a gap for the AUX selector */ ++ BUG_ON((clock_data->num_std_parents > AUX_SEL) && ++ strcmp("-", clock_data->parents[AUX_SEL])); ++ ++ memset(&init, 0, sizeof(init)); ++ init.parent_names = clock_data->parents; ++ init.num_parents = ++ clock_data->num_std_parents + clock_data->num_aux_parents; ++ init.name = clock_data->name; ++ init.flags = clock_data->flags | CLK_IGNORE_UNUSED; ++ init.ops = &rp1_clk_ops; ++ ++ clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); ++ if (!clock) ++ return NULL; ++ ++ clock->clockman = clockman; ++ clock->data = clock_data; ++ 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); ++ const void *data; ++}; ++ ++/* Assignment helper macros for different clock types. */ ++#define _REGISTER(f, ...) { .clk_register = f, .data = __VA_ARGS__ } ++ ++#define REGISTER_PLL_CORE(...) _REGISTER(&rp1_register_pll_core, \ ++ &(struct rp1_pll_core_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_PLL(...) _REGISTER(&rp1_register_pll, \ ++ &(struct rp1_pll_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_PLL_PH(...) _REGISTER(&rp1_register_pll_ph, \ ++ &(struct rp1_pll_ph_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_PLL_DIV(...) _REGISTER(&rp1_register_pll_divider, \ ++ &(struct rp1_pll_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_CLK(...) _REGISTER(&rp1_register_clock, \ ++ &(struct rp1_clock_data) \ ++ {__VA_ARGS__}) ++ ++static const struct rp1_clk_desc clk_desc_array[] = { ++ [RP1_PLL_SYS_CORE] = REGISTER_PLL_CORE( ++ .name = "pll_sys_core", ++ .cs_reg = PLL_SYS_CS, ++ .pwr_reg = PLL_SYS_PWR, ++ .fbdiv_int_reg = PLL_SYS_FBDIV_INT, ++ .fbdiv_frac_reg = PLL_SYS_FBDIV_FRAC, ++ ), ++ ++ [RP1_PLL_AUDIO_CORE] = REGISTER_PLL_CORE( ++ .name = "pll_audio_core", ++ .cs_reg = PLL_AUDIO_CS, ++ .pwr_reg = PLL_AUDIO_PWR, ++ .fbdiv_int_reg = PLL_AUDIO_FBDIV_INT, ++ .fbdiv_frac_reg = PLL_AUDIO_FBDIV_FRAC, ++ ), ++ ++ [RP1_PLL_VIDEO_CORE] = REGISTER_PLL_CORE( ++ .name = "pll_video_core", ++ .cs_reg = PLL_VIDEO_CS, ++ .pwr_reg = PLL_VIDEO_PWR, ++ .fbdiv_int_reg = PLL_VIDEO_FBDIV_INT, ++ .fbdiv_frac_reg = PLL_VIDEO_FBDIV_FRAC, ++ ), ++ ++ [RP1_PLL_SYS] = REGISTER_PLL( ++ .name = "pll_sys", ++ .source_pll = "pll_sys_core", ++ .ctrl_reg = PLL_SYS_PRIM, ++ .fc0_src = FC_NUM(0, 2), ++ ), ++ ++ [RP1_PLL_AUDIO] = REGISTER_PLL( ++ .name = "pll_audio", ++ .source_pll = "pll_audio_core", ++ .ctrl_reg = PLL_AUDIO_PRIM, ++ .fc0_src = FC_NUM(4, 2), ++ ), ++ ++ [RP1_PLL_VIDEO] = REGISTER_PLL( ++ .name = "pll_video", ++ .source_pll = "pll_video_core", ++ .ctrl_reg = PLL_VIDEO_PRIM, ++ .fc0_src = FC_NUM(3, 2), ++ ), ++ ++ [RP1_PLL_SYS_PRI_PH] = REGISTER_PLL_PH( ++ .name = "pll_sys_pri_ph", ++ .source_pll = "pll_sys", ++ .ph_reg = PLL_SYS_PRIM, ++ .fixed_divider = 2, ++ .phase = RP1_PLL_PHASE_0, ++ .fc0_src = FC_NUM(1, 2), ++ ), ++ ++ [RP1_PLL_AUDIO_PRI_PH] = REGISTER_PLL_PH( ++ .name = "pll_audio_pri_ph", ++ .source_pll = "pll_audio", ++ .ph_reg = PLL_AUDIO_PRIM, ++ .fixed_divider = 2, ++ .phase = RP1_PLL_PHASE_0, ++ .fc0_src = FC_NUM(5, 1), ++ ), ++ ++ [RP1_PLL_SYS_SEC] = REGISTER_PLL_DIV( ++ .name = "pll_sys_sec", ++ .source_pll = "pll_sys_core", ++ .ctrl_reg = PLL_SYS_SEC, ++ .fc0_src = FC_NUM(2, 2), ++ ), ++ ++ [RP1_PLL_AUDIO_SEC] = REGISTER_PLL_DIV( ++ .name = "pll_audio_sec", ++ .source_pll = "pll_audio_core", ++ .ctrl_reg = PLL_AUDIO_SEC, ++ .fc0_src = FC_NUM(6, 2), ++ ), ++ ++ [RP1_PLL_VIDEO_SEC] = REGISTER_PLL_DIV( ++ .name = "pll_video_sec", ++ .source_pll = "pll_video_core", ++ .ctrl_reg = PLL_VIDEO_SEC, ++ .fc0_src = FC_NUM(5, 3), ++ ), ++ ++ [RP1_CLK_SYS] = REGISTER_CLK( ++ .name = "clk_sys", ++ .parents = {"xosc", "-", "pll_sys"}, ++ .num_std_parents = 3, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_SYS_CTRL, ++ .div_int_reg = CLK_SYS_DIV_INT, ++ .sel_reg = CLK_SYS_SEL, ++ .div_int_max = DIV_INT_24BIT_MAX, ++ .fc0_src = FC_NUM(0, 4), ++ .clk_src_mask = 0x3, ++ ), ++ ++ [RP1_CLK_SLOW_SYS] = REGISTER_CLK( ++ .name = "clk_slow_sys", ++ .parents = {"xosc"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_SLOW_SYS_CTRL, ++ .div_int_reg = CLK_SLOW_SYS_DIV_INT, ++ .sel_reg = CLK_SLOW_SYS_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(1, 4), ++ .clk_src_mask = 0x1, ++ ), ++ ++ [RP1_CLK_UART] = REGISTER_CLK( ++ .name = "clk_uart", ++ .parents = {"pll_sys_pri_ph", ++ "pll_video", ++ "xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_UART_CTRL, ++ .div_int_reg = CLK_UART_DIV_INT, ++ .sel_reg = CLK_UART_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(6, 7), ++ ), ++ ++ [RP1_CLK_ETH] = REGISTER_CLK( ++ .name = "clk_eth", ++ .parents = {"-"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_ETH_CTRL, ++ .div_int_reg = CLK_ETH_DIV_INT, ++ .sel_reg = CLK_ETH_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(4, 6), ++ ), ++ ++ [RP1_CLK_PWM0] = REGISTER_CLK( ++ .name = "clk_pwm0", ++ .parents = {"pll_audio_pri_ph", ++ "pll_video_sec", ++ "xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_PWM0_CTRL, ++ .div_int_reg = CLK_PWM0_DIV_INT, ++ .div_frac_reg = CLK_PWM0_DIV_FRAC, ++ .sel_reg = CLK_PWM0_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(0, 5), ++ ), ++ ++ [RP1_CLK_PWM1] = REGISTER_CLK( ++ .name = "clk_pwm1", ++ .parents = {"pll_audio_pri_ph", ++ "pll_video_sec", ++ "xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_PWM1_CTRL, ++ .div_int_reg = CLK_PWM1_DIV_INT, ++ .div_frac_reg = CLK_PWM1_DIV_FRAC, ++ .sel_reg = CLK_PWM1_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(1, 5), ++ ), ++ ++ [RP1_CLK_AUDIO_IN] = REGISTER_CLK( ++ .name = "clk_audio_in", ++ .parents = {"-"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_AUDIO_IN_CTRL, ++ .div_int_reg = CLK_AUDIO_IN_DIV_INT, ++ .sel_reg = CLK_AUDIO_IN_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(2, 5), ++ ), ++ ++ [RP1_CLK_AUDIO_OUT] = REGISTER_CLK( ++ .name = "clk_audio_out", ++ .parents = {"-"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_AUDIO_OUT_CTRL, ++ .div_int_reg = CLK_AUDIO_OUT_DIV_INT, ++ .sel_reg = CLK_AUDIO_OUT_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(3, 5), ++ ), ++ ++ [RP1_CLK_I2S] = REGISTER_CLK( ++ .name = "clk_i2s", ++ .parents = {"xosc", ++ "pll_audio", ++ "pll_audio_sec"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_I2S_CTRL, ++ .div_int_reg = CLK_I2S_DIV_INT, ++ .sel_reg = CLK_I2S_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(4, 4), ++ ), ++ ++ [RP1_CLK_MIPI0_CFG] = REGISTER_CLK( ++ .name = "clk_mipi0_cfg", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_MIPI0_CFG_CTRL, ++ .div_int_reg = CLK_MIPI0_CFG_DIV_INT, ++ .sel_reg = CLK_MIPI0_CFG_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(4, 5), ++ ), ++ ++ [RP1_CLK_MIPI1_CFG] = REGISTER_CLK( ++ .name = "clk_mipi1_cfg", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_MIPI1_CFG_CTRL, ++ .div_int_reg = CLK_MIPI1_CFG_DIV_INT, ++ .sel_reg = CLK_MIPI1_CFG_SEL, ++ .clk_src_mask = 1, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 6), ++ ), ++ ++ [RP1_CLK_ETH_TSU] = REGISTER_CLK( ++ .name = "clk_eth_tsu", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_ETH_TSU_CTRL, ++ .div_int_reg = CLK_ETH_TSU_DIV_INT, ++ .sel_reg = CLK_ETH_TSU_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 7), ++ ), ++ ++ [RP1_CLK_ADC] = REGISTER_CLK( ++ .name = "clk_adc", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_ADC_CTRL, ++ .div_int_reg = CLK_ADC_DIV_INT, ++ .sel_reg = CLK_ADC_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 5), ++ ), ++ ++ [RP1_CLK_SDIO_TIMER] = REGISTER_CLK( ++ .name = "clk_sdio_timer", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_SDIO_TIMER_CTRL, ++ .div_int_reg = CLK_SDIO_TIMER_DIV_INT, ++ .sel_reg = CLK_SDIO_TIMER_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(3, 4), ++ ), ++ ++ [RP1_CLK_SDIO_ALT_SRC] = REGISTER_CLK( ++ .name = "clk_sdio_alt_src", ++ .parents = {"pll_sys"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_SDIO_ALT_SRC_CTRL, ++ .div_int_reg = CLK_SDIO_ALT_SRC_DIV_INT, ++ .sel_reg = CLK_SDIO_ALT_SRC_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 4), ++ ), ++ ++ [RP1_CLK_GP0] = REGISTER_CLK( ++ .name = "clk_gp0", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP0_CTRL, ++ .div_int_reg = CLK_GP0_DIV_INT, ++ .div_frac_reg = CLK_GP0_DIV_FRAC, ++ .sel_reg = CLK_GP0_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(0, 1), ++ ), ++ ++ [RP1_CLK_GP1] = REGISTER_CLK( ++ .name = "clk_gp1", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP1_CTRL, ++ .div_int_reg = CLK_GP1_DIV_INT, ++ .div_frac_reg = CLK_GP1_DIV_FRAC, ++ .sel_reg = CLK_GP1_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(1, 1), ++ ), ++ ++ [RP1_CLK_GP2] = REGISTER_CLK( ++ .name = "clk_gp2", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP2_CTRL, ++ .div_int_reg = CLK_GP2_DIV_INT, ++ .div_frac_reg = CLK_GP2_DIV_FRAC, ++ .sel_reg = CLK_GP2_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(2, 1), ++ ), ++ ++ [RP1_CLK_GP3] = REGISTER_CLK( ++ .name = "clk_gp3", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP3_CTRL, ++ .div_int_reg = CLK_GP3_DIV_INT, ++ .div_frac_reg = CLK_GP3_DIV_FRAC, ++ .sel_reg = CLK_GP3_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(3, 1), ++ ), ++ ++ [RP1_CLK_GP4] = REGISTER_CLK( ++ .name = "clk_gp4", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP4_CTRL, ++ .div_int_reg = CLK_GP4_DIV_INT, ++ .div_frac_reg = CLK_GP4_DIV_FRAC, ++ .sel_reg = CLK_GP4_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(4, 1), ++ ), ++ ++ [RP1_CLK_GP5] = REGISTER_CLK( ++ .name = "clk_gp5", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP5_CTRL, ++ .div_int_reg = CLK_GP5_DIV_INT, ++ .div_frac_reg = CLK_GP5_DIV_FRAC, ++ .sel_reg = CLK_GP5_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(5, 1), ++ ), ++ ++ [RP1_CLK_VEC] = REGISTER_CLK( ++ .name = "clk_vec", ++ .parents = {"pll_sys_pri_ph", ++ "pll_video_sec", ++ "pll_video", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3", ++ "clk_gp4"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_VEC_CTRL, ++ .div_int_reg = VIDEO_CLK_VEC_DIV_INT, ++ .sel_reg = VIDEO_CLK_VEC_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let VEC driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(0, 6), ++ ), ++ ++ [RP1_CLK_DPI] = REGISTER_CLK( ++ .name = "clk_dpi", ++ .parents = {"pll_sys", ++ "pll_video_sec", ++ "pll_video", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3", ++ "clk_gp4"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_DPI_CTRL, ++ .div_int_reg = VIDEO_CLK_DPI_DIV_INT, ++ .sel_reg = VIDEO_CLK_DPI_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let DPI driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(1, 6), ++ ), ++ ++ [RP1_CLK_MIPI0_DPI] = REGISTER_CLK( ++ .name = "clk_mipi0_dpi", ++ .parents = {"pll_sys", ++ "pll_video_sec", ++ "pll_video", ++ "clksrc_mipi0_dsi_byteclk", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_MIPI0_DPI_CTRL, ++ .div_int_reg = VIDEO_CLK_MIPI0_DPI_DIV_INT, ++ .div_frac_reg = VIDEO_CLK_MIPI0_DPI_DIV_FRAC, ++ .sel_reg = VIDEO_CLK_MIPI0_DPI_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let DSI driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(2, 6), ++ ), ++ ++ [RP1_CLK_MIPI1_DPI] = REGISTER_CLK( ++ .name = "clk_mipi1_dpi", ++ .parents = {"pll_sys", ++ "pll_video_sec", ++ "pll_video", ++ "clksrc_mipi1_dsi_byteclk", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_MIPI1_DPI_CTRL, ++ .div_int_reg = VIDEO_CLK_MIPI1_DPI_DIV_INT, ++ .div_frac_reg = VIDEO_CLK_MIPI1_DPI_DIV_FRAC, ++ .sel_reg = VIDEO_CLK_MIPI1_DPI_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let DSI driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(3, 6), ++ ), ++}; ++ ++static bool rp1_clk_claimed[ARRAY_SIZE(clk_desc_array)]; ++ ++static bool rp1_clk_is_claimed(const char *name) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) { ++ if (clk_desc_array[i].data) { ++ const char *clk_name = *(const char **)(clk_desc_array[i].data); ++ ++ if (!strcmp(name, clk_name)) ++ return rp1_clk_claimed[i]; ++ } ++ } ++ ++ return false; ++} ++ ++static int rp1_clk_probe(struct platform_device *pdev) ++{ ++ const struct rp1_clk_desc *desc; ++ struct device *dev = &pdev->dev; ++ struct rp1_clockman *clockman; ++ struct resource *res; ++ struct clk_hw **hws; ++ const size_t asize = ARRAY_SIZE(clk_desc_array); ++ u32 chip_id, platform; ++ unsigned int i; ++ u32 clk_id; ++ int ret; ++ ++ clockman = devm_kzalloc(dev, struct_size(clockman, onecell.hws, asize), ++ GFP_KERNEL); ++ if (!clockman) ++ return -ENOMEM; ++ ++ rp1_get_platform(&chip_id, &platform); ++ ++ spin_lock_init(&clockman->regs_lock); ++ clockman->dev = dev; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ clockman->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(clockman->regs)) ++ return PTR_ERR(clockman->regs); ++ ++ memset(rp1_clk_claimed, 0, sizeof(rp1_clk_claimed)); ++ for (i = 0; ++ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", ++ i, &clk_id); ++ i++) ++ rp1_clk_claimed[clk_id] = true; ++ ++ platform_set_drvdata(pdev, clockman); ++ ++ clockman->onecell.num = asize; ++ hws = clockman->onecell.hws; ++ ++ for (i = 0; i < asize; i++) { ++ desc = &clk_desc_array[i]; ++ if (desc->clk_register && desc->data) ++ hws[i] = desc->clk_register(clockman, desc->data); ++ } ++ ++ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, ++ &clockman->onecell); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static const struct of_device_id rp1_clk_of_match[] = { ++ { .compatible = "raspberrypi,rp1-clocks" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, rp1_clk_of_match); ++ ++static struct platform_driver rp1_clk_driver = { ++ .driver = { ++ .name = "rp1-clk", ++ .of_match_table = rp1_clk_of_match, ++ }, ++ .probe = rp1_clk_probe, ++}; ++ ++static int __init __rp1_clk_driver_init(void) ++{ ++ return platform_driver_register(&rp1_clk_driver); ++} ++postcore_initcall(__rp1_clk_driver_init); ++ ++MODULE_AUTHOR("Naushir Patuck "); ++MODULE_DESCRIPTION("RP1 clock driver"); ++MODULE_LICENSE("GPL"); +--- a/include/dt-bindings/clock/rp1.h ++++ b/include/dt-bindings/clock/rp1.h +@@ -13,39 +13,40 @@ + + #define RP1_PLL_SYS_PRI_PH 6 + #define RP1_PLL_SYS_SEC_PH 7 ++#define RP1_PLL_AUDIO_PRI_PH 8 + +-#define RP1_PLL_SYS_SEC 8 +-#define RP1_PLL_AUDIO_SEC 9 +-#define RP1_PLL_VIDEO_SEC 10 ++#define RP1_PLL_SYS_SEC 9 ++#define RP1_PLL_AUDIO_SEC 10 ++#define RP1_PLL_VIDEO_SEC 11 + +-#define RP1_CLK_SYS 11 +-#define RP1_CLK_SLOW_SYS 12 +-#define RP1_CLK_DMA 13 +-#define RP1_CLK_UART 14 +-#define RP1_CLK_ETH 15 +-#define RP1_CLK_PWM0 16 +-#define RP1_CLK_PWM1 17 +-#define RP1_CLK_AUDIO_IN 18 +-#define RP1_CLK_AUDIO_OUT 19 +-#define RP1_CLK_I2S 20 +-#define RP1_CLK_MIPI0_CFG 21 +-#define RP1_CLK_MIPI1_CFG 22 +-#define RP1_CLK_PCIE_AUX 23 +-#define RP1_CLK_USBH0_MICROFRAME 24 +-#define RP1_CLK_USBH1_MICROFRAME 25 +-#define RP1_CLK_USBH0_SUSPEND 26 +-#define RP1_CLK_USBH1_SUSPEND 27 +-#define RP1_CLK_ETH_TSU 28 +-#define RP1_CLK_ADC 29 +-#define RP1_CLK_SDIO_TIMER 30 +-#define RP1_CLK_SDIO_ALT_SRC 31 +-#define RP1_CLK_GP0 32 +-#define RP1_CLK_GP1 33 +-#define RP1_CLK_GP2 34 +-#define RP1_CLK_GP3 35 +-#define RP1_CLK_GP4 36 +-#define RP1_CLK_GP5 37 +-#define RP1_CLK_VEC 38 +-#define RP1_CLK_DPI 39 +-#define RP1_CLK_MIPI0_DPI 40 +-#define RP1_CLK_MIPI1_DPI 41 ++#define RP1_CLK_SYS 12 ++#define RP1_CLK_SLOW_SYS 13 ++#define RP1_CLK_DMA 14 ++#define RP1_CLK_UART 15 ++#define RP1_CLK_ETH 16 ++#define RP1_CLK_PWM0 17 ++#define RP1_CLK_PWM1 18 ++#define RP1_CLK_AUDIO_IN 19 ++#define RP1_CLK_AUDIO_OUT 20 ++#define RP1_CLK_I2S 21 ++#define RP1_CLK_MIPI0_CFG 22 ++#define RP1_CLK_MIPI1_CFG 23 ++#define RP1_CLK_PCIE_AUX 24 ++#define RP1_CLK_USBH0_MICROFRAME 25 ++#define RP1_CLK_USBH1_MICROFRAME 26 ++#define RP1_CLK_USBH0_SUSPEND 27 ++#define RP1_CLK_USBH1_SUSPEND 28 ++#define RP1_CLK_ETH_TSU 29 ++#define RP1_CLK_ADC 30 ++#define RP1_CLK_SDIO_TIMER 31 ++#define RP1_CLK_SDIO_ALT_SRC 32 ++#define RP1_CLK_GP0 33 ++#define RP1_CLK_GP1 34 ++#define RP1_CLK_GP2 35 ++#define RP1_CLK_GP3 36 ++#define RP1_CLK_GP4 37 ++#define RP1_CLK_GP5 38 ++#define RP1_CLK_VEC 39 ++#define RP1_CLK_DPI 40 ++#define RP1_CLK_MIPI0_DPI 41 ++#define RP1_CLK_MIPI1_DPI 42 diff --git a/target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch b/target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch new file mode 100644 index 0000000000..d0180a65ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch @@ -0,0 +1,60 @@ +From 19b934ce3763c9465c5c80302f7c142d30b75869 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 28 Oct 2022 14:13:30 +0100 +Subject: [PATCH] dt-bindings: pinctrl: Add bindings for Raspberry Pi RP1 + +Signed-off-by: Phil Elwell +--- + include/dt-bindings/pinctrl/rp1.h | 46 +++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + create mode 100644 include/dt-bindings/pinctrl/rp1.h + +--- /dev/null ++++ b/include/dt-bindings/pinctrl/rp1.h +@@ -0,0 +1,46 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Header providing constants for RP1 pinctrl bindings. ++ * ++ * Copyright (C) 2019-2022 Raspberry Pi Ltd. ++ */ ++ ++#ifndef __DT_BINDINGS_PINCTRL_RP1_H__ ++#define __DT_BINDINGS_PINCTRL_RP1_H__ ++ ++/* brcm,function property */ ++#define RP1_FSEL_GPIO_IN 0 ++#define RP1_FSEL_GPIO_OUT 1 ++#define RP1_FSEL_ALT0_LEGACY 4 ++#define RP1_FSEL_ALT1_LEGACY 5 ++#define RP1_FSEL_ALT2_LEGACY 6 ++#define RP1_FSEL_ALT3_LEGACY 7 ++#define RP1_FSEL_ALT4_LEGACY 3 ++#define RP1_FSEL_ALT5_LEGACY 2 ++#define RP1_FSEL_ALT0 0x08 ++#define RP1_FSEL_ALT0INV 0x09 ++#define RP1_FSEL_ALT1 0x0a ++#define RP1_FSEL_ALT1INV 0x0b ++#define RP1_FSEL_ALT2 0x0c ++#define RP1_FSEL_ALT2INV 0x0d ++#define RP1_FSEL_ALT3 0x0e ++#define RP1_FSEL_ALT3INV 0x0f ++#define RP1_FSEL_ALT4 0x10 ++#define RP1_FSEL_ALT4INV 0x11 ++#define RP1_FSEL_ALT5 0x12 ++#define RP1_FSEL_ALT5INV 0x13 ++#define RP1_FSEL_ALT6 0x14 ++#define RP1_FSEL_ALT6INV 0x15 ++#define RP1_FSEL_ALT7 0x16 ++#define RP1_FSEL_ALT7INV 0x17 ++#define RP1_FSEL_ALT8 0x18 ++#define RP1_FSEL_ALT8INV 0x19 ++#define RP1_FSEL_NONE 0x1a ++ ++/* brcm,pull property */ ++#define RP1_PUD_OFF 0 ++#define RP1_PUD_DOWN 1 ++#define RP1_PUD_UP 2 ++#define RP1_PUD_KEEP 3 ++ ++#endif /* __DT_BINDINGS_PINCTRL_RP1_H__ */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0876-pinctrl-Add-rp1-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0876-pinctrl-Add-rp1-driver.patch new file mode 100644 index 0000000000..c824cddb51 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0876-pinctrl-Add-rp1-driver.patch @@ -0,0 +1,1666 @@ +From 4d4cc5be473a7767052122a87393a83d10f9ed41 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 10 Oct 2022 14:21:11 +0100 +Subject: [PATCH] pinctrl: Add rp1 driver + +RP1 exposes GPIOs. Add a pinctrl driver to allow control of those. + +Signed-off-by: Phil Elwell +--- + drivers/pinctrl/Kconfig | 7 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/pinctrl-rp1.c | 1571 +++++++++++++++++++++++++++++ + include/dt-bindings/pinctrl/rp1.h | 46 - + 4 files changed, 1579 insertions(+), 46 deletions(-) + create mode 100644 drivers/pinctrl/pinctrl-rp1.c + delete mode 100644 include/dt-bindings/pinctrl/rp1.h + +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -512,6 +512,13 @@ config PINCTRL_ZYNQMP + This driver can also be built as a module. If so, the module + will be called pinctrl-zynqmp. + ++config PINCTRL_RP1 ++ bool "Pinctrl driver for RP1" ++ select PINMUX ++ select PINCONF ++ select GENERIC_PINCONF ++ select GPIOLIB_IRQCHIP ++ + source "drivers/pinctrl/actions/Kconfig" + source "drivers/pinctrl/aspeed/Kconfig" + source "drivers/pinctrl/bcm/Kconfig" +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -42,6 +42,7 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-p + obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o + obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o + obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o ++obj-$(CONFIG_PINCTRL_RP1) += pinctrl-rp1.o + obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o + obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o + obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o +--- /dev/null ++++ b/drivers/pinctrl/pinctrl-rp1.c +@@ -0,0 +1,1571 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for Raspberry Pi RP1 GPIO unit (pinctrl + GPIO) ++ * ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ * ++ * This driver is inspired by: ++ * pinctrl-bcm2835.c, please see original file for copyright information ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "core.h" ++#include "pinconf.h" ++#include "pinctrl-utils.h" ++ ++#define MODULE_NAME "pinctrl-rp1" ++#define RP1_NUM_GPIOS 54 ++#define RP1_NUM_BANKS 3 ++ ++#define RP1_RW_OFFSET 0x0000 ++#define RP1_XOR_OFFSET 0x1000 ++#define RP1_SET_OFFSET 0x2000 ++#define RP1_CLR_OFFSET 0x3000 ++ ++#define RP1_GPIO_STATUS 0x0000 ++#define RP1_GPIO_CTRL 0x0004 ++ ++#define RP1_GPIO_PCIE_INTE 0x011c ++#define RP1_GPIO_PCIE_INTS 0x0124 ++ ++#define RP1_GPIO_EVENTS_SHIFT_RAW 20 ++#define RP1_GPIO_STATUS_FALLING BIT(20) ++#define RP1_GPIO_STATUS_RISING BIT(21) ++#define RP1_GPIO_STATUS_LOW BIT(22) ++#define RP1_GPIO_STATUS_HIGH BIT(23) ++ ++#define RP1_GPIO_EVENTS_SHIFT_FILTERED 24 ++#define RP1_GPIO_STATUS_F_FALLING BIT(24) ++#define RP1_GPIO_STATUS_F_RISING BIT(25) ++#define RP1_GPIO_STATUS_F_LOW BIT(26) ++#define RP1_GPIO_STATUS_F_HIGH BIT(27) ++ ++#define RP1_GPIO_CTRL_FUNCSEL_LSB 0 ++#define RP1_GPIO_CTRL_FUNCSEL_MASK 0x0000001f ++#define RP1_GPIO_CTRL_OUTOVER_LSB 12 ++#define RP1_GPIO_CTRL_OUTOVER_MASK 0x00003000 ++#define RP1_GPIO_CTRL_OEOVER_LSB 14 ++#define RP1_GPIO_CTRL_OEOVER_MASK 0x0000c000 ++#define RP1_GPIO_CTRL_INOVER_LSB 16 ++#define RP1_GPIO_CTRL_INOVER_MASK 0x00030000 ++#define RP1_GPIO_CTRL_IRQEN_FALLING BIT(20) ++#define RP1_GPIO_CTRL_IRQEN_RISING BIT(21) ++#define RP1_GPIO_CTRL_IRQEN_LOW BIT(22) ++#define RP1_GPIO_CTRL_IRQEN_HIGH BIT(23) ++#define RP1_GPIO_CTRL_IRQEN_F_FALLING BIT(24) ++#define RP1_GPIO_CTRL_IRQEN_F_RISING BIT(25) ++#define RP1_GPIO_CTRL_IRQEN_F_LOW BIT(26) ++#define RP1_GPIO_CTRL_IRQEN_F_HIGH BIT(27) ++#define RP1_GPIO_CTRL_IRQRESET BIT(28) ++#define RP1_GPIO_CTRL_IRQOVER_LSB 30 ++#define RP1_GPIO_CTRL_IRQOVER_MASK 0xc0000000 ++ ++#define RP1_INT_EDGE_FALLING BIT(0) ++#define RP1_INT_EDGE_RISING BIT(1) ++#define RP1_INT_LEVEL_LOW BIT(2) ++#define RP1_INT_LEVEL_HIGH BIT(3) ++#define RP1_INT_MASK 0xf ++ ++#define RP1_INT_EDGE_BOTH (RP1_INT_EDGE_FALLING | \ ++ RP1_INT_EDGE_RISING) ++#define RP1_PUD_OFF 0 ++#define RP1_PUD_DOWN 1 ++#define RP1_PUD_UP 2 ++ ++#define RP1_FSEL_COUNT 9 ++ ++#define RP1_FSEL_ALT0 0x00 ++#define RP1_FSEL_GPIO 0x05 ++#define RP1_FSEL_NONE 0x09 ++#define RP1_FSEL_NONE_HW 0x1f ++ ++#define RP1_DIR_OUTPUT 0 ++#define RP1_DIR_INPUT 1 ++ ++#define RP1_OUTOVER_PERI 0 ++#define RP1_OUTOVER_INVPERI 1 ++#define RP1_OUTOVER_LOW 2 ++#define RP1_OUTOVER_HIGH 3 ++ ++#define RP1_OEOVER_PERI 0 ++#define RP1_OEOVER_INVPERI 1 ++#define RP1_OEOVER_DISABLE 2 ++#define RP1_OEOVER_ENABLE 3 ++ ++#define RP1_INOVER_PERI 0 ++#define RP1_INOVER_INVPERI 1 ++#define RP1_INOVER_LOW 2 ++#define RP1_INOVER_HIGH 3 ++ ++#define RP1_RIO_OUT 0x00 ++#define RP1_RIO_OE 0x04 ++#define RP1_RIO_IN 0x08 ++ ++#define RP1_PAD_SLEWFAST_MASK 0x00000001 ++#define RP1_PAD_SLEWFAST_LSB 0 ++#define RP1_PAD_SCHMITT_MASK 0x00000002 ++#define RP1_PAD_SCHMITT_LSB 1 ++#define RP1_PAD_PULL_MASK 0x0000000c ++#define RP1_PAD_PULL_LSB 2 ++#define RP1_PAD_DRIVE_MASK 0x00000030 ++#define RP1_PAD_DRIVE_LSB 4 ++#define RP1_PAD_IN_ENABLE_MASK 0x00000040 ++#define RP1_PAD_IN_ENABLE_LSB 6 ++#define RP1_PAD_OUT_DISABLE_MASK 0x00000080 ++#define RP1_PAD_OUT_DISABLE_LSB 7 ++ ++#define RP1_PAD_DRIVE_2MA 0x00000000 ++#define RP1_PAD_DRIVE_4MA 0x00000010 ++#define RP1_PAD_DRIVE_8MA 0x00000020 ++#define RP1_PAD_DRIVE_12MA 0x00000030 ++ ++#define FLD_GET(r, f) (((r) & (f ## _MASK)) >> (f ## _LSB)) ++#define FLD_SET(r, f, v) r = (((r) & ~(f ## _MASK)) | ((v) << (f ## _LSB))) ++ ++#define FUNC(f) \ ++ [func_##f] = #f ++#define RP1_MAX_FSEL 8 ++#define PIN(i, f0, f1, f2, f3, f4, f5, f6, f7, f8) \ ++ [i] = { \ ++ .funcs = { \ ++ func_##f0, \ ++ func_##f1, \ ++ func_##f2, \ ++ func_##f3, \ ++ func_##f4, \ ++ func_##f5, \ ++ func_##f6, \ ++ func_##f7, \ ++ func_##f8, \ ++ }, \ ++ } ++ ++#define LEGACY_MAP(n, f0, f1, f2, f3, f4, f5) \ ++ [n] = { \ ++ func_gpio, \ ++ func_gpio, \ ++ func_##f5, \ ++ func_##f4, \ ++ func_##f0, \ ++ func_##f1, \ ++ func_##f2, \ ++ func_##f3, \ ++ } ++ ++struct rp1_iobank_desc { ++ int min_gpio; ++ int num_gpios; ++ int gpio_offset; ++ int inte_offset; ++ int ints_offset; ++ int rio_offset; ++ int pads_offset; ++}; ++ ++struct rp1_pin_info { ++ u8 num; ++ u8 bank; ++ u8 offset; ++ u8 fsel; ++ u8 irq_type; ++ ++ void __iomem *gpio; ++ void __iomem *rio; ++ void __iomem *inte; ++ void __iomem *ints; ++ void __iomem *pad; ++}; ++ ++enum funcs { ++ func_alt0, ++ func_alt1, ++ func_alt2, ++ func_alt3, ++ func_alt4, ++ func_gpio, ++ func_alt6, ++ func_alt7, ++ func_alt8, ++ func_none, ++ func_aaud, ++ func_dcd0, ++ func_dpi, ++ func_dsi0_te_ext, ++ func_dsi1_te_ext, ++ func_dsr0, ++ func_dtr0, ++ func_gpclk0, ++ func_gpclk1, ++ func_gpclk2, ++ func_gpclk3, ++ func_gpclk4, ++ func_gpclk5, ++ func_i2c0, ++ func_i2c1, ++ func_i2c2, ++ func_i2c3, ++ func_i2c4, ++ func_i2c5, ++ func_i2c6, ++ func_i2s0, ++ func_i2s1, ++ func_i2s2, ++ func_ir, ++ func_mic, ++ func_pcie_clkreq_n, ++ func_pio, ++ func_proc_rio, ++ func_pwm0, ++ func_pwm1, ++ func_ri0, ++ func_sd0, ++ func_sd1, ++ func_spi0, ++ func_spi1, ++ func_spi2, ++ func_spi3, ++ func_spi4, ++ func_spi5, ++ func_spi6, ++ func_spi7, ++ func_spi8, ++ func_uart0, ++ func_uart1, ++ func_uart2, ++ func_uart3, ++ func_uart4, ++ func_uart5, ++ func_vbus0, ++ func_vbus1, ++ func_vbus2, ++ func_vbus3, ++ func__, ++ func_count = func__, ++ func_invalid = func__, ++}; ++ ++struct rp1_pin_funcs { ++ u8 funcs[RP1_FSEL_COUNT]; ++}; ++ ++struct rp1_pinctrl { ++ struct device *dev; ++ void __iomem *gpio_base; ++ void __iomem *rio_base; ++ void __iomem *pads_base; ++ int irq[RP1_NUM_BANKS]; ++ struct rp1_pin_info pins[RP1_NUM_GPIOS]; ++ ++ struct pinctrl_dev *pctl_dev; ++ struct gpio_chip gpio_chip; ++ struct pinctrl_gpio_range gpio_range; ++ ++ raw_spinlock_t irq_lock[RP1_NUM_BANKS]; ++}; ++ ++const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] = { ++ /* gpio inte ints rio pads */ ++ { 0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 }, ++ { 28, 6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 }, ++ { 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 }, ++}; ++ ++/* pins are just named GPIO0..GPIO53 */ ++#define RP1_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a) ++static struct pinctrl_pin_desc rp1_gpio_pins[] = { ++ RP1_GPIO_PIN(0), ++ RP1_GPIO_PIN(1), ++ RP1_GPIO_PIN(2), ++ RP1_GPIO_PIN(3), ++ RP1_GPIO_PIN(4), ++ RP1_GPIO_PIN(5), ++ RP1_GPIO_PIN(6), ++ RP1_GPIO_PIN(7), ++ RP1_GPIO_PIN(8), ++ RP1_GPIO_PIN(9), ++ RP1_GPIO_PIN(10), ++ RP1_GPIO_PIN(11), ++ RP1_GPIO_PIN(12), ++ RP1_GPIO_PIN(13), ++ RP1_GPIO_PIN(14), ++ RP1_GPIO_PIN(15), ++ RP1_GPIO_PIN(16), ++ RP1_GPIO_PIN(17), ++ RP1_GPIO_PIN(18), ++ RP1_GPIO_PIN(19), ++ RP1_GPIO_PIN(20), ++ RP1_GPIO_PIN(21), ++ RP1_GPIO_PIN(22), ++ RP1_GPIO_PIN(23), ++ RP1_GPIO_PIN(24), ++ RP1_GPIO_PIN(25), ++ RP1_GPIO_PIN(26), ++ RP1_GPIO_PIN(27), ++ RP1_GPIO_PIN(28), ++ RP1_GPIO_PIN(29), ++ RP1_GPIO_PIN(30), ++ RP1_GPIO_PIN(31), ++ RP1_GPIO_PIN(32), ++ RP1_GPIO_PIN(33), ++ RP1_GPIO_PIN(34), ++ RP1_GPIO_PIN(35), ++ RP1_GPIO_PIN(36), ++ RP1_GPIO_PIN(37), ++ RP1_GPIO_PIN(38), ++ RP1_GPIO_PIN(39), ++ RP1_GPIO_PIN(40), ++ RP1_GPIO_PIN(41), ++ RP1_GPIO_PIN(42), ++ RP1_GPIO_PIN(43), ++ RP1_GPIO_PIN(44), ++ RP1_GPIO_PIN(45), ++ RP1_GPIO_PIN(46), ++ RP1_GPIO_PIN(47), ++ RP1_GPIO_PIN(48), ++ RP1_GPIO_PIN(49), ++ RP1_GPIO_PIN(50), ++ RP1_GPIO_PIN(51), ++ RP1_GPIO_PIN(52), ++ RP1_GPIO_PIN(53), ++}; ++ ++/* one pin per group */ ++static const char * const rp1_gpio_groups[] = { ++ "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", ++ "gpio28", ++ "gpio29", ++ "gpio30", ++ "gpio31", ++ "gpio32", ++ "gpio33", ++ "gpio34", ++ "gpio35", ++ "gpio36", ++ "gpio37", ++ "gpio38", ++ "gpio39", ++ "gpio40", ++ "gpio41", ++ "gpio42", ++ "gpio43", ++ "gpio44", ++ "gpio45", ++ "gpio46", ++ "gpio47", ++ "gpio48", ++ "gpio49", ++ "gpio50", ++ "gpio51", ++ "gpio52", ++ "gpio53", ++}; ++ ++static const char * const rp1_func_names[] = { ++ FUNC(alt0), ++ FUNC(alt1), ++ FUNC(alt2), ++ FUNC(alt3), ++ FUNC(alt4), ++ FUNC(gpio), ++ FUNC(alt6), ++ FUNC(alt7), ++ FUNC(alt8), ++ FUNC(none), ++ FUNC(aaud), ++ FUNC(dcd0), ++ FUNC(dpi), ++ FUNC(dsi0_te_ext), ++ FUNC(dsi1_te_ext), ++ FUNC(dsr0), ++ FUNC(dtr0), ++ FUNC(gpclk0), ++ FUNC(gpclk1), ++ FUNC(gpclk2), ++ FUNC(gpclk3), ++ FUNC(gpclk4), ++ FUNC(gpclk5), ++ FUNC(i2c0), ++ FUNC(i2c1), ++ FUNC(i2c2), ++ FUNC(i2c3), ++ FUNC(i2c4), ++ FUNC(i2c5), ++ FUNC(i2c6), ++ FUNC(i2s0), ++ FUNC(i2s1), ++ FUNC(i2s2), ++ FUNC(ir), ++ FUNC(mic), ++ FUNC(pcie_clkreq_n), ++ FUNC(pio), ++ FUNC(proc_rio), ++ FUNC(pwm0), ++ FUNC(pwm1), ++ FUNC(ri0), ++ FUNC(sd0), ++ FUNC(sd1), ++ FUNC(spi0), ++ FUNC(spi1), ++ FUNC(spi2), ++ FUNC(spi3), ++ FUNC(spi4), ++ FUNC(spi5), ++ FUNC(spi6), ++ FUNC(spi7), ++ FUNC(spi8), ++ FUNC(uart0), ++ FUNC(uart1), ++ FUNC(uart2), ++ FUNC(uart3), ++ FUNC(uart4), ++ FUNC(uart5), ++ FUNC(vbus0), ++ FUNC(vbus1), ++ FUNC(vbus2), ++ FUNC(vbus3), ++ [func_invalid] = "?" ++}; ++ ++static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] = { ++ PIN(0, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2), ++ PIN(1, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2), ++ PIN(2, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2), ++ PIN(3, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2), ++ PIN(4, gpclk0, dpi, uart2, i2c2, ri0, gpio, proc_rio, pio, spi3), ++ PIN(5, gpclk1, dpi, uart2, i2c2, dtr0, gpio, proc_rio, pio, spi3), ++ PIN(6, gpclk2, dpi, uart2, i2c3, dcd0, gpio, proc_rio, pio, spi3), ++ PIN(7, spi0, dpi, uart2, i2c3, dsr0, gpio, proc_rio, pio, spi3), ++ PIN(8, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4), ++ PIN(9, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4), ++ PIN(10, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4), ++ PIN(11, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4), ++ PIN(12, pwm0, dpi, uart4, i2c2, aaud, gpio, proc_rio, pio, spi5), ++ PIN(13, pwm0, dpi, uart4, i2c2, aaud, gpio, proc_rio, pio, spi5), ++ PIN(14, pwm0, dpi, uart4, i2c3, uart0, gpio, proc_rio, pio, spi5), ++ PIN(15, pwm0, dpi, uart4, i2c3, uart0, gpio, proc_rio, pio, spi5), ++ PIN(16, spi1, dpi, dsi0_te_ext, _, uart0, gpio, proc_rio, pio, _), ++ PIN(17, spi1, dpi, dsi1_te_ext, _, uart0, gpio, proc_rio, pio, _), ++ PIN(18, spi1, dpi, i2s0, pwm0, i2s1, gpio, proc_rio, pio, gpclk1), ++ PIN(19, spi1, dpi, i2s0, pwm0, i2s1, gpio, proc_rio, pio, _), ++ PIN(20, spi1, dpi, i2s0, gpclk0, i2s1, gpio, proc_rio, pio, _), ++ PIN(21, spi1, dpi, i2s0, gpclk1, i2s1, gpio, proc_rio, pio, _), ++ PIN(22, sd0, dpi, i2s0, i2c3, i2s1, gpio, proc_rio, pio, _), ++ PIN(23, sd0, dpi, i2s0, i2c3, i2s1, gpio, proc_rio, pio, _), ++ PIN(24, sd0, dpi, i2s0, _, i2s1, gpio, proc_rio, pio, spi2), ++ PIN(25, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi3), ++ PIN(26, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi5), ++ PIN(27, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi1), ++ PIN(28, sd1, i2c4, i2s2, spi6, vbus0, gpio, proc_rio, _, _), ++ PIN(29, sd1, i2c4, i2s2, spi6, vbus0, gpio, proc_rio, _, _), ++ PIN(30, sd1, i2c5, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(31, sd1, i2c5, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(32, sd1, gpclk3, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(33, sd1, gpclk4, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(34, pwm1, gpclk3, vbus0, i2c4, mic, gpio, proc_rio, _, _), ++ PIN(35, spi8, pwm1, vbus0, i2c4, mic, gpio, proc_rio, _, _), ++ PIN(36, spi8, uart5, pcie_clkreq_n, i2c5, mic, gpio, proc_rio, _, _), ++ PIN(37, spi8, uart5, mic, i2c5, pcie_clkreq_n, gpio, proc_rio, _, _), ++ PIN(38, spi8, uart5, mic, i2c6, aaud, gpio, proc_rio, dsi0_te_ext, _), ++ PIN(39, spi8, uart5, mic, i2c6, aaud, gpio, proc_rio, dsi1_te_ext, _), ++ PIN(40, pwm1, uart5, i2c4, spi6, aaud, gpio, proc_rio, _, _), ++ PIN(41, pwm1, uart5, i2c4, spi6, aaud, gpio, proc_rio, _, _), ++ PIN(42, gpclk5, uart5, vbus1, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(43, gpclk4, uart5, vbus1, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(44, gpclk5, i2c5, pwm1, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(45, pwm1, i2c5, spi7, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(46, gpclk3, i2c4, spi7, mic, i2s2, gpio, proc_rio, dsi0_te_ext, _), ++ PIN(47, gpclk5, i2c4, spi7, mic, i2s2, gpio, proc_rio, dsi1_te_ext, _), ++ PIN(48, pwm1, pcie_clkreq_n, spi7, mic, uart5, gpio, proc_rio, _, _), ++ PIN(49, spi8, spi7, i2c5, aaud, uart5, gpio, proc_rio, _, _), ++ PIN(50, spi8, spi7, i2c5, aaud, vbus2, gpio, proc_rio, _, _), ++ PIN(51, spi8, spi7, i2c6, aaud, vbus2, gpio, proc_rio, _, _), ++ PIN(52, spi8, _, i2c6, aaud, vbus3, gpio, proc_rio, _, _), ++ PIN(53, spi8, spi7, _, pcie_clkreq_n, vbus3, gpio, proc_rio, _, _), ++}; ++ ++static const u8 legacy_fsel_map[][8] = { ++ LEGACY_MAP(0, i2c0, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(1, i2c0, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(2, i2c1, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(3, i2c1, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(4, gpclk0, _, dpi, spi3, uart2, i2c2), ++ LEGACY_MAP(5, gpclk1, _, dpi, spi3, uart2, i2c2), ++ LEGACY_MAP(6, gpclk2, _, dpi, spi3, uart2, i2c3), ++ LEGACY_MAP(7, spi0, _, dpi, spi3, uart2, i2c3), ++ LEGACY_MAP(8, spi0, _, dpi, _, uart3, i2c0), ++ LEGACY_MAP(9, spi0, _, dpi, _, uart3, i2c0), ++ LEGACY_MAP(10, spi0, _, dpi, _, uart3, i2c1), ++ LEGACY_MAP(11, spi0, _, dpi, _, uart3, i2c1), ++ LEGACY_MAP(12, pwm0, _, dpi, spi5, uart4, i2c2), ++ LEGACY_MAP(13, pwm0, _, dpi, spi5, uart4, i2c2), ++ LEGACY_MAP(14, uart0, _, dpi, spi5, uart4, _), ++ LEGACY_MAP(15, uart0, _, dpi, spi5, uart4, _), ++ LEGACY_MAP(16, _, _, dpi, uart0, spi1, _), ++ LEGACY_MAP(17, _, _, dpi, uart0, spi1, _), ++ LEGACY_MAP(18, i2s0, _, dpi, _, spi1, pwm0), ++ LEGACY_MAP(19, i2s0, _, dpi, _, spi1, pwm0), ++ LEGACY_MAP(20, i2s0, _, dpi, _, spi1, gpclk0), ++ LEGACY_MAP(21, i2s0, _, dpi, _, spi1, gpclk1), ++ LEGACY_MAP(22, sd0, _, dpi, _, _, i2c3), ++ LEGACY_MAP(23, sd0, _, dpi, _, _, i2c3), ++ LEGACY_MAP(24, sd0, _, dpi, _, _, spi2), ++ LEGACY_MAP(25, sd0, _, dpi, _, _, spi3), ++ LEGACY_MAP(26, sd0, _, dpi, _, _, spi5), ++ LEGACY_MAP(27, sd0, _, dpi, _, _, _), ++}; ++ ++static const char * const irq_type_names[] = { ++ [IRQ_TYPE_NONE] = "none", ++ [IRQ_TYPE_EDGE_RISING] = "edge-rising", ++ [IRQ_TYPE_EDGE_FALLING] = "edge-falling", ++ [IRQ_TYPE_EDGE_BOTH] = "edge-both", ++ [IRQ_TYPE_LEVEL_HIGH] = "level-high", ++ [IRQ_TYPE_LEVEL_LOW] = "level-low", ++}; ++ ++static int rp1_pinconf_set(struct pinctrl_dev *pctldev, ++ unsigned int offset, unsigned long *configs, ++ unsigned int num_configs); ++ ++static struct rp1_pin_info *rp1_get_pin(struct gpio_chip *chip, ++ unsigned int offset) ++{ ++ struct rp1_pinctrl *pc = gpiochip_get_data(chip); ++ ++ if (pc && offset < RP1_NUM_GPIOS) ++ return &pc->pins[offset]; ++ return NULL; ++} ++ ++static struct rp1_pin_info *rp1_get_pin_pctl(struct pinctrl_dev *pctldev, ++ unsigned int offset) ++{ ++ struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ if (pc && offset < RP1_NUM_GPIOS) ++ return &pc->pins[offset]; ++ return NULL; ++} ++ ++static void rp1_pad_update(struct rp1_pin_info *pin, u32 clr, u32 set) ++{ ++ u32 padctrl = readl(pin->pad); ++ ++ padctrl &= ~clr; ++ padctrl |= set; ++ ++ writel(padctrl, pin->pad); ++} ++ ++static void rp1_input_enable(struct rp1_pin_info *pin, int value) ++{ ++ rp1_pad_update(pin, RP1_PAD_IN_ENABLE_MASK, ++ value ? RP1_PAD_IN_ENABLE_MASK : 0); ++} ++ ++static void rp1_output_enable(struct rp1_pin_info *pin, int value) ++{ ++ rp1_pad_update(pin, RP1_PAD_OUT_DISABLE_MASK, ++ value ? 0 : RP1_PAD_OUT_DISABLE_MASK); ++} ++ ++static u32 rp1_get_fsel(struct rp1_pin_info *pin) ++{ ++ u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL); ++ u32 oeover = FLD_GET(ctrl, RP1_GPIO_CTRL_OEOVER); ++ u32 fsel = FLD_GET(ctrl, RP1_GPIO_CTRL_FUNCSEL); ++ ++ if (oeover != RP1_OEOVER_PERI || fsel >= RP1_FSEL_COUNT) ++ fsel = RP1_FSEL_NONE; ++ ++ return fsel; ++} ++ ++static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel) ++{ ++ u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL); ++ ++ if (fsel >= RP1_FSEL_COUNT) ++ fsel = RP1_FSEL_NONE_HW; ++ ++ rp1_input_enable(pin, 1); ++ rp1_output_enable(pin, 1); ++ ++ if (fsel == RP1_FSEL_NONE) { ++ FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_DISABLE); ++ } else { ++ FLD_SET(ctrl, RP1_GPIO_CTRL_OUTOVER, RP1_OUTOVER_PERI); ++ 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); ++} ++ ++static int rp1_get_dir(struct rp1_pin_info *pin) ++{ ++ return !(readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ? ++ RP1_DIR_INPUT : RP1_DIR_OUTPUT; ++} ++ ++static void rp1_set_dir(struct rp1_pin_info *pin, bool is_input) ++{ ++ int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET; ++ ++ writel(1 << pin->offset, 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)); ++} ++ ++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)); ++} ++ ++static int rp1_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ int ret; ++ ++ if (!pin) ++ return -EINVAL; ++ ret = rp1_get_value(pin); ++ return ret; ++} ++ ++static void rp1_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ ++ if (pin) ++ rp1_set_value(pin, value); ++} ++ ++static int rp1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ u32 fsel; ++ ++ if (!pin) ++ return -EINVAL; ++ fsel = rp1_get_fsel(pin); ++ if (fsel != RP1_FSEL_GPIO) ++ return -EINVAL; ++ return (rp1_get_dir(pin) == RP1_DIR_OUTPUT) ? ++ GPIO_LINE_DIRECTION_OUT : ++ GPIO_LINE_DIRECTION_IN; ++} ++ ++static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ ++ if (!pin) ++ return -EINVAL; ++ rp1_set_dir(pin, RP1_DIR_INPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ return 0; ++} ++ ++static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ ++ if (!pin) ++ return -EINVAL; ++ rp1_set_value(pin, value); ++ rp1_set_dir(pin, RP1_DIR_OUTPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ return 0; ++} ++ ++static int rp1_gpio_set_config(struct gpio_chip *gc, unsigned offset, ++ unsigned long config) ++{ ++ struct rp1_pinctrl *pc = gpiochip_get_data(gc); ++ unsigned long configs[] = { config }; ++ ++ return rp1_pinconf_set(pc->pctl_dev, offset, configs, ++ ARRAY_SIZE(configs)); ++} ++ ++static const struct gpio_chip rp1_gpio_chip = { ++ .label = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .request = gpiochip_generic_request, ++ .free = gpiochip_generic_free, ++ .direction_input = rp1_gpio_direction_input, ++ .direction_output = rp1_gpio_direction_output, ++ .get_direction = rp1_gpio_get_direction, ++ .get = rp1_gpio_get, ++ .set = rp1_gpio_set, ++ .base = -1, ++ .set_config = rp1_gpio_set_config, ++ .ngpio = RP1_NUM_GPIOS, ++ .can_sleep = false, ++}; ++ ++static void rp1_gpio_irq_handler(struct irq_desc *desc) ++{ ++ struct gpio_chip *chip = irq_desc_get_handler_data(desc); ++ struct rp1_pinctrl *pc = gpiochip_get_data(chip); ++ struct irq_chip *host_chip = irq_desc_get_chip(desc); ++ const struct rp1_iobank_desc *bank; ++ int irq = irq_desc_get_irq(desc); ++ unsigned long ints; ++ int b; ++ ++ if (pc->irq[0] == irq) ++ bank = &rp1_iobanks[0]; ++ else if (pc->irq[1] == irq) ++ bank = &rp1_iobanks[1]; ++ else ++ bank = &rp1_iobanks[2]; ++ ++ chained_irq_enter(host_chip, desc); ++ ++ ints = readl(pc->gpio_base + bank->ints_offset); ++ for_each_set_bit(b, &ints, 32) { ++ struct rp1_pin_info *pin = rp1_get_pin(chip, b); ++ ++ writel(RP1_GPIO_CTRL_IRQRESET, ++ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++ generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain, ++ bank->gpio_offset + b)); ++ } ++ ++ chained_irq_exit(host_chip, desc); ++} ++ ++static void rp1_gpio_irq_config(struct rp1_pin_info *pin, bool enable) ++{ ++ writel(1 << pin->offset, ++ pin->inte + (enable ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); ++ if (!enable) ++ /* Clear any latched events */ ++ writel(RP1_GPIO_CTRL_IRQRESET, ++ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++} ++ ++static void rp1_gpio_irq_enable(struct irq_data *data) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ ++ rp1_gpio_irq_config(pin, true); ++} ++ ++static void rp1_gpio_irq_disable(struct irq_data *data) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ ++ rp1_gpio_irq_config(pin, false); ++} ++ ++static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type) ++{ ++ u32 irq_flags; ++ ++ switch (type) { ++ case IRQ_TYPE_NONE: ++ irq_flags = 0; ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ irq_flags = RP1_INT_EDGE_RISING; ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ irq_flags = RP1_INT_EDGE_FALLING; ++ break; ++ case IRQ_TYPE_EDGE_BOTH: ++ irq_flags = RP1_INT_EDGE_RISING | RP1_INT_EDGE_FALLING; ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ irq_flags = RP1_INT_LEVEL_HIGH; ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ irq_flags = RP1_INT_LEVEL_LOW; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ /* Clear them all */ ++ writel(RP1_INT_MASK << RP1_GPIO_EVENTS_SHIFT_RAW, ++ pin->gpio + RP1_CLR_OFFSET + RP1_GPIO_CTRL); ++ /* Set those that are needed */ ++ writel(irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW, ++ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++ pin->irq_type = type; ++ ++ return 0; ++} ++ ++static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ struct rp1_pinctrl *pc = gpiochip_get_data(chip); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ int bank = pin->bank; ++ unsigned long flags; ++ int ret; ++ ++ raw_spin_lock_irqsave(&pc->irq_lock[bank], flags); ++ ++ ret = rp1_irq_set_type(pin, type); ++ if (!ret) { ++ if (type & IRQ_TYPE_EDGE_BOTH) ++ irq_set_handler_locked(data, handle_edge_irq); ++ else ++ irq_set_handler_locked(data, handle_level_irq); ++ } ++ ++ raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags); ++ ++ return ret; ++} ++ ++static void rp1_gpio_irq_ack(struct irq_data *data) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ ++ /* Clear any latched events */ ++ writel(RP1_GPIO_CTRL_IRQRESET, pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++} ++ ++static struct irq_chip rp1_gpio_irq_chip = { ++ .name = MODULE_NAME, ++ .irq_enable = rp1_gpio_irq_enable, ++ .irq_disable = rp1_gpio_irq_disable, ++ .irq_set_type = rp1_gpio_irq_set_type, ++ .irq_ack = rp1_gpio_irq_ack, ++ .irq_mask = rp1_gpio_irq_disable, ++ .irq_unmask = rp1_gpio_irq_enable, ++ .flags = IRQCHIP_IMMUTABLE, ++}; ++ ++static int rp1_pctl_get_groups_count(struct pinctrl_dev *pctldev) ++{ ++ return ARRAY_SIZE(rp1_gpio_groups); ++} ++ ++static const char *rp1_pctl_get_group_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ return rp1_gpio_groups[selector]; ++} ++ ++static enum funcs rp1_get_fsel_func(unsigned pin, unsigned fsel) ++{ ++ if (pin < RP1_NUM_GPIOS) { ++ if (fsel < RP1_FSEL_COUNT) ++ return rp1_gpio_pin_funcs[pin].funcs[fsel]; ++ else if (fsel == RP1_FSEL_NONE) ++ return func_none; ++ } ++ return func_invalid; ++} ++ ++static int rp1_pctl_get_group_pins(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const unsigned **pins, ++ unsigned *num_pins) ++{ ++ *pins = &rp1_gpio_pins[selector].number; ++ *num_pins = 1; ++ ++ return 0; ++} ++ ++static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, ++ struct seq_file *s, ++ unsigned offset) ++{ ++ struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ struct gpio_chip *chip = &pc->gpio_chip; ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ u32 fsel = rp1_get_fsel(pin); ++ enum funcs func = rp1_get_fsel_func(offset, fsel); ++ int value = rp1_get_value(pin); ++ int irq = irq_find_mapping(chip->irq.domain, offset); ++ ++ seq_printf(s, "function %s (%s) in %s; irq %d (%s)", ++ rp1_func_names[fsel], rp1_func_names[func], ++ value ? "hi" : "lo", ++ irq, irq_type_names[pin->irq_type]); ++} ++ ++static void rp1_pctl_dt_free_map(struct pinctrl_dev *pctldev, ++ struct pinctrl_map *maps, unsigned num_maps) ++{ ++ int i; ++ ++ for (i = 0; i < num_maps; i++) ++ if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN) ++ kfree(maps[i].data.configs.configs); ++ ++ kfree(maps); ++} ++ ++static int rp1_pctl_legacy_map_func(struct rp1_pinctrl *pc, ++ struct device_node *np, u32 pin, u32 fnum, ++ struct pinctrl_map *maps, ++ unsigned int *num_maps) ++{ ++ struct pinctrl_map *map = &maps[*num_maps]; ++ enum funcs func; ++ ++ if (fnum >= ARRAY_SIZE(legacy_fsel_map[0])) { ++ dev_err(pc->dev, "%pOF: invalid brcm,function %d\n", np, fnum); ++ return -EINVAL; ++ } ++ ++ func = legacy_fsel_map[pin][fnum]; ++ if (func == func_invalid) { ++ dev_err(pc->dev, "%pOF: brcm,function %d not supported on pin %d\n", ++ np, fnum, pin); ++ } ++ ++ map->type = PIN_MAP_TYPE_MUX_GROUP; ++ map->data.mux.group = rp1_gpio_groups[pin]; ++ map->data.mux.function = rp1_func_names[func]; ++ (*num_maps)++; ++ ++ return 0; ++} ++ ++static int rp1_pctl_legacy_map_pull(struct rp1_pinctrl *pc, ++ struct device_node *np, u32 pin, u32 pull, ++ struct pinctrl_map *maps, ++ unsigned int *num_maps) ++{ ++ struct pinctrl_map *map = &maps[*num_maps]; ++ enum pin_config_param param; ++ unsigned long *configs; ++ ++ switch (pull) { ++ case RP1_PUD_OFF: ++ param = PIN_CONFIG_BIAS_DISABLE; ++ break; ++ case RP1_PUD_DOWN: ++ param = PIN_CONFIG_BIAS_PULL_DOWN; ++ break; ++ case RP1_PUD_UP: ++ param = PIN_CONFIG_BIAS_PULL_UP; ++ break; ++ default: ++ dev_err(pc->dev, "%pOF: invalid brcm,pull %d\n", np, pull); ++ return -EINVAL; ++ } ++ ++ configs = kzalloc(sizeof(*configs), GFP_KERNEL); ++ if (!configs) ++ return -ENOMEM; ++ ++ configs[0] = pinconf_to_config_packed(param, 0); ++ map->type = PIN_MAP_TYPE_CONFIGS_PIN; ++ map->data.configs.group_or_pin = rp1_gpio_pins[pin].name; ++ map->data.configs.configs = configs; ++ map->data.configs.num_configs = 1; ++ (*num_maps)++; ++ ++ return 0; ++} ++ ++static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, ++ struct device_node *np, ++ struct pinctrl_map **map, ++ unsigned int *num_maps) ++{ ++ struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ struct property *pins, *funcs, *pulls; ++ int num_pins, num_funcs, num_pulls, maps_per_pin; ++ struct pinctrl_map *maps; ++ unsigned long *configs = NULL; ++ const char *function = NULL; ++ unsigned int reserved_maps; ++ int num_configs = 0; ++ int i, err; ++ u32 pin, func, pull; ++ ++ /* Check for legacy pin declaration */ ++ pins = of_find_property(np, "brcm,pins", NULL); ++ ++ if (!pins) /* Assume generic bindings in this node */ ++ return pinconf_generic_dt_node_to_map_all(pctldev, np, map, num_maps); ++ ++ funcs = of_find_property(np, "brcm,function", NULL); ++ if (!funcs) ++ of_property_read_string(np, "function", &function); ++ ++ pulls = of_find_property(np, "brcm,pull", NULL); ++ if (!pulls) ++ pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); ++ ++ if (!function && !funcs && !num_configs && !pulls) { ++ dev_err(pc->dev, ++ "%pOF: no function, brcm,function, brcm,pull, etc.\n", ++ np); ++ return -EINVAL; ++ } ++ ++ num_pins = pins->length / 4; ++ num_funcs = funcs ? (funcs->length / 4) : 0; ++ num_pulls = pulls ? (pulls->length / 4) : 0; ++ ++ if (num_funcs > 1 && num_funcs != num_pins) { ++ dev_err(pc->dev, ++ "%pOF: brcm,function must have 1 or %d entries\n", ++ np, num_pins); ++ return -EINVAL; ++ } ++ ++ if (num_pulls > 1 && num_pulls != num_pins) { ++ dev_err(pc->dev, ++ "%pOF: brcm,pull must have 1 or %d entries\n", ++ np, num_pins); ++ return -EINVAL; ++ } ++ ++ maps_per_pin = 0; ++ if (function || num_funcs) ++ maps_per_pin++; ++ if (num_configs || num_pulls) ++ maps_per_pin++; ++ reserved_maps = num_pins * maps_per_pin; ++ maps = kcalloc(reserved_maps, sizeof(*maps), GFP_KERNEL); ++ if (!maps) ++ return -ENOMEM; ++ ++ *num_maps = 0; ++ ++ for (i = 0; i < num_pins; i++) { ++ err = of_property_read_u32_index(np, "brcm,pins", i, &pin); ++ if (err) ++ goto out; ++ if (pin >= ARRAY_SIZE(legacy_fsel_map)) { ++ dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", ++ np, pin); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ if (num_funcs) { ++ err = of_property_read_u32_index(np, "brcm,function", ++ (num_funcs > 1) ? i : 0, ++ &func); ++ if (err) ++ goto out; ++ err = rp1_pctl_legacy_map_func(pc, np, pin, func, ++ maps, num_maps); ++ } else if (function) { ++ err = pinctrl_utils_add_map_mux(pctldev, &maps, ++ &reserved_maps, num_maps, ++ rp1_gpio_groups[pin], ++ function); ++ } ++ ++ if (err) ++ goto out; ++ ++ if (num_pulls) { ++ err = of_property_read_u32_index(np, "brcm,pull", ++ (num_pulls > 1) ? i : 0, ++ &pull); ++ if (err) ++ goto out; ++ err = rp1_pctl_legacy_map_pull(pc, np, pin, pull, ++ maps, num_maps); ++ } else if (num_configs) { ++ err = pinctrl_utils_add_map_configs(pctldev, &maps, ++ &reserved_maps, num_maps, ++ rp1_gpio_groups[pin], ++ configs, num_configs, ++ PIN_MAP_TYPE_CONFIGS_PIN); ++ } ++ ++ if (err) ++ goto out; ++ } ++ ++ *map = maps; ++ ++ return 0; ++ ++out: ++ rp1_pctl_dt_free_map(pctldev, maps, reserved_maps); ++ return err; ++} ++ ++static const struct pinctrl_ops rp1_pctl_ops = { ++ .get_groups_count = rp1_pctl_get_groups_count, ++ .get_group_name = rp1_pctl_get_group_name, ++ .get_group_pins = rp1_pctl_get_group_pins, ++ .pin_dbg_show = rp1_pctl_pin_dbg_show, ++ .dt_node_to_map = rp1_pctl_dt_node_to_map, ++ .dt_free_map = rp1_pctl_dt_free_map, ++}; ++ ++static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ u32 fsel = rp1_get_fsel(pin); ++ ++ /* Return non-GPIOs to GPIO_IN */ ++ if (fsel != RP1_FSEL_GPIO) { ++ rp1_set_dir(pin, RP1_DIR_INPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ } ++ ++ return 0; ++} ++ ++static int rp1_pmx_get_functions_count(struct pinctrl_dev *pctldev) ++{ ++ return func_count; ++} ++ ++static const char *rp1_pmx_get_function_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ return (selector < func_count) ? rp1_func_names[selector] : NULL; ++} ++ ++static int rp1_pmx_get_function_groups(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const char * const **groups, ++ unsigned * const num_groups) ++{ ++ /* every pin can do every function */ ++ *groups = rp1_gpio_groups; ++ *num_groups = ARRAY_SIZE(rp1_gpio_groups); ++ ++ return 0; ++} ++ ++static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned func_selector, ++ unsigned group_selector) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, group_selector); ++ const u8 *pin_funcs; ++ int fsel; ++ ++ /* func_selector is an enum funcs, so needs translation */ ++ ++ if (func_selector >= RP1_FSEL_COUNT) { ++ /* Convert to an fsel number */ ++ pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs; ++ for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) { ++ if (pin_funcs[fsel] == func_selector) ++ break; ++ } ++ } else { ++ fsel = (int)func_selector; ++ } ++ ++ if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE) ++ return -EINVAL; ++ ++ rp1_set_fsel(pin, fsel); ++ ++ return 0; ++} ++ ++static void rp1_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned offset) ++{ ++ (void)rp1_pmx_free(pctldev, offset); ++} ++ ++static int rp1_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned offset, ++ bool input) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ ++ rp1_set_dir(pin, input); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ ++ return 0; ++} ++ ++static const struct pinmux_ops rp1_pmx_ops = { ++ .free = rp1_pmx_free, ++ .get_functions_count = rp1_pmx_get_functions_count, ++ .get_function_name = rp1_pmx_get_function_name, ++ .get_function_groups = rp1_pmx_get_function_groups, ++ .set_mux = rp1_pmx_set, ++ .gpio_disable_free = rp1_pmx_gpio_disable_free, ++ .gpio_set_direction = rp1_pmx_gpio_set_direction, ++}; ++ ++static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg) ++{ ++ u32 padctrl = readl(pin->pad); ++ ++ FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3); ++ ++ writel(padctrl, pin->pad); ++} ++ ++/* Generic pinconf methods */ ++ ++static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, ++ unsigned long *configs, unsigned int num_configs) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ u32 param, arg; ++ int i; ++ ++ if (!pin) ++ return -EINVAL; ++ ++ for (i = 0; i < num_configs; i++) { ++ param = pinconf_to_config_param(configs[i]); ++ arg = pinconf_to_config_argument(configs[i]); ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ rp1_pull_config_set(pin, RP1_PUD_OFF); ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ rp1_pull_config_set(pin, RP1_PUD_DOWN); ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_UP: ++ rp1_pull_config_set(pin, RP1_PUD_UP); ++ break; ++ ++ case PIN_CONFIG_INPUT_ENABLE: ++ rp1_input_enable(pin, arg); ++ break; ++ ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ rp1_output_enable(pin, arg); ++ break; ++ ++ case PIN_CONFIG_OUTPUT: ++ rp1_set_value(pin, arg); ++ rp1_set_dir(pin, RP1_DIR_OUTPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ break; ++ ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ rp1_pad_update(pin, RP1_PAD_SCHMITT_MASK, ++ arg ? RP1_PAD_SCHMITT_MASK : 0); ++ break; ++ ++ case PIN_CONFIG_SLEW_RATE: ++ rp1_pad_update(pin, RP1_PAD_SLEWFAST_MASK, ++ arg ? RP1_PAD_SLEWFAST_MASK : 0); ++ break; ++ ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ switch (arg) { ++ case 2: ++ arg = RP1_PAD_DRIVE_2MA; ++ break; ++ case 4: ++ arg = RP1_PAD_DRIVE_4MA; ++ break; ++ case 8: ++ arg = RP1_PAD_DRIVE_8MA; ++ break; ++ case 12: ++ arg = RP1_PAD_DRIVE_12MA; ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ rp1_pad_update(pin, RP1_PAD_DRIVE_MASK, arg); ++ break; ++ ++ default: ++ return -ENOTSUPP; ++ ++ } /* switch param type */ ++ } /* for each config */ ++ ++ return 0; ++} ++ ++static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned offset, ++ unsigned long *config) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ enum pin_config_param param = pinconf_to_config_param(*config); ++ u32 padctrl; ++ u32 arg; ++ ++ if (!pin) ++ return -EINVAL; ++ ++ padctrl = readl(pin->pad); ++ ++ switch (param) { ++ case PIN_CONFIG_INPUT_ENABLE: ++ arg = !!(padctrl & RP1_PAD_IN_ENABLE_MASK); ++ break; ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ arg = !(padctrl & RP1_PAD_OUT_DISABLE_MASK); ++ break; ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ arg = !!(padctrl & RP1_PAD_SCHMITT_MASK); ++ break; ++ case PIN_CONFIG_SLEW_RATE: ++ arg = !!(padctrl & RP1_PAD_SLEWFAST_MASK); ++ break; ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ switch (padctrl & RP1_PAD_DRIVE_MASK) { ++ case RP1_PAD_DRIVE_2MA: ++ arg = 2; ++ break; ++ case RP1_PAD_DRIVE_4MA: ++ arg = 4; ++ break; ++ case RP1_PAD_DRIVE_8MA: ++ arg = 8; ++ break; ++ case RP1_PAD_DRIVE_12MA: ++ arg = 12; ++ break; ++ } ++ break; ++ case PIN_CONFIG_BIAS_DISABLE: ++ arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_OFF << RP1_PAD_PULL_LSB)); ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_DOWN << RP1_PAD_PULL_LSB)); ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_UP: ++ arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_UP << RP1_PAD_PULL_LSB)); ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ *config = pinconf_to_config_packed(param, arg); ++ ++ return 0; ++} ++ ++static const struct pinconf_ops rp1_pinconf_ops = { ++ .is_generic = true, ++ .pin_config_get = rp1_pinconf_get, ++ .pin_config_set = rp1_pinconf_set, ++}; ++ ++static struct pinctrl_desc rp1_pinctrl_desc = { ++ .name = MODULE_NAME, ++ .pins = rp1_gpio_pins, ++ .npins = ARRAY_SIZE(rp1_gpio_pins), ++ .pctlops = &rp1_pctl_ops, ++ .pmxops = &rp1_pmx_ops, ++ .confops = &rp1_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static struct pinctrl_gpio_range rp1_pinctrl_gpio_range = { ++ .name = MODULE_NAME, ++ .npins = RP1_NUM_GPIOS, ++}; ++ ++static const struct of_device_id rp1_pinctrl_match[] = { ++ { ++ .compatible = "raspberrypi,rp1-gpio", ++ .data = &rp1_pinconf_ops, ++ }, ++ {} ++}; ++ ++static inline void __iomem *devm_auto_iomap(struct platform_device *pdev, ++ unsigned int index) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ ++ if (np) ++ return devm_of_iomap(dev, np, (int)index, NULL); ++ else ++ return devm_platform_ioremap_resource(pdev, index); ++} ++ ++static int rp1_pinctrl_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct rp1_pinctrl *pc; ++ struct gpio_irq_chip *girq; ++ int err, i; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_pins) != RP1_NUM_GPIOS); ++ BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_groups) != RP1_NUM_GPIOS); ++ ++ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, pc); ++ pc->dev = dev; ++ ++ pc->gpio_base = devm_auto_iomap(pdev, 0); ++ if (IS_ERR(pc->gpio_base)) { ++ dev_err(dev, "could not get GPIO IO memory\n"); ++ return PTR_ERR(pc->gpio_base); ++ } ++ ++ pc->rio_base = devm_auto_iomap(pdev, 1); ++ if (IS_ERR(pc->rio_base)) { ++ dev_err(dev, "could not get RIO IO memory\n"); ++ return PTR_ERR(pc->rio_base); ++ } ++ ++ pc->pads_base = devm_auto_iomap(pdev, 2); ++ if (IS_ERR(pc->pads_base)) { ++ dev_err(dev, "could not get PADS IO memory\n"); ++ return PTR_ERR(pc->pads_base); ++ } ++ ++ pc->gpio_chip = rp1_gpio_chip; ++ pc->gpio_chip.parent = dev; ++ ++ for (i = 0; i < RP1_NUM_BANKS; i++) { ++ const struct rp1_iobank_desc *bank = &rp1_iobanks[i]; ++ int j; ++ ++ for (j = 0; j < bank->num_gpios; j++) { ++ struct rp1_pin_info *pin = ++ &pc->pins[bank->min_gpio + j]; ++ ++ pin->num = bank->min_gpio + j; ++ pin->bank = i; ++ pin->offset = j; ++ ++ pin->gpio = pc->gpio_base + bank->gpio_offset + ++ j * sizeof(u32) * 2; ++ pin->inte = pc->gpio_base + bank->inte_offset; ++ pin->ints = pc->gpio_base + bank->ints_offset; ++ pin->rio = pc->rio_base + bank->rio_offset; ++ pin->pad = pc->pads_base + bank->pads_offset + ++ j * sizeof(u32); ++ } ++ ++ 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); ++ ++ girq = &pc->gpio_chip.irq; ++ girq->chip = &rp1_gpio_irq_chip; ++ girq->parent_handler = rp1_gpio_irq_handler; ++ girq->num_parents = RP1_NUM_BANKS; ++ girq->parents = pc->irq; ++ ++ /* ++ * Use the same handler for all groups: this is necessary ++ * since we use one gpiochip to cover all lines - the ++ * irq handler then needs to figure out which group and ++ * bank that was firing the IRQ and look up the per-group ++ * and bank data. ++ */ ++ for (i = 0; i < RP1_NUM_BANKS; i++) { ++ pc->irq[i] = irq_of_parse_and_map(np, i); ++ if (!pc->irq[i]) { ++ girq->num_parents = i; ++ break; ++ } ++ } ++ ++ girq->default_type = IRQ_TYPE_NONE; ++ girq->handler = handle_level_irq; ++ ++ err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc); ++ if (err) { ++ dev_err(dev, "could not add GPIO chip\n"); ++ return err; ++ } ++ ++ pc->gpio_range = rp1_pinctrl_gpio_range; ++ pc->gpio_range.base = pc->gpio_chip.base; ++ pc->gpio_range.gc = &pc->gpio_chip; ++ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); ++ ++ return 0; ++} ++ ++static struct platform_driver rp1_pinctrl_driver = { ++ .probe = rp1_pinctrl_probe, ++ .driver = { ++ .name = MODULE_NAME, ++ .of_match_table = rp1_pinctrl_match, ++ .suppress_bind_attrs = true, ++ }, ++}; ++builtin_platform_driver(rp1_pinctrl_driver); +--- a/include/dt-bindings/pinctrl/rp1.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* +- * Header providing constants for RP1 pinctrl bindings. +- * +- * Copyright (C) 2019-2022 Raspberry Pi Ltd. +- */ +- +-#ifndef __DT_BINDINGS_PINCTRL_RP1_H__ +-#define __DT_BINDINGS_PINCTRL_RP1_H__ +- +-/* brcm,function property */ +-#define RP1_FSEL_GPIO_IN 0 +-#define RP1_FSEL_GPIO_OUT 1 +-#define RP1_FSEL_ALT0_LEGACY 4 +-#define RP1_FSEL_ALT1_LEGACY 5 +-#define RP1_FSEL_ALT2_LEGACY 6 +-#define RP1_FSEL_ALT3_LEGACY 7 +-#define RP1_FSEL_ALT4_LEGACY 3 +-#define RP1_FSEL_ALT5_LEGACY 2 +-#define RP1_FSEL_ALT0 0x08 +-#define RP1_FSEL_ALT0INV 0x09 +-#define RP1_FSEL_ALT1 0x0a +-#define RP1_FSEL_ALT1INV 0x0b +-#define RP1_FSEL_ALT2 0x0c +-#define RP1_FSEL_ALT2INV 0x0d +-#define RP1_FSEL_ALT3 0x0e +-#define RP1_FSEL_ALT3INV 0x0f +-#define RP1_FSEL_ALT4 0x10 +-#define RP1_FSEL_ALT4INV 0x11 +-#define RP1_FSEL_ALT5 0x12 +-#define RP1_FSEL_ALT5INV 0x13 +-#define RP1_FSEL_ALT6 0x14 +-#define RP1_FSEL_ALT6INV 0x15 +-#define RP1_FSEL_ALT7 0x16 +-#define RP1_FSEL_ALT7INV 0x17 +-#define RP1_FSEL_ALT8 0x18 +-#define RP1_FSEL_ALT8INV 0x19 +-#define RP1_FSEL_NONE 0x1a +- +-/* brcm,pull property */ +-#define RP1_PUD_OFF 0 +-#define RP1_PUD_DOWN 1 +-#define RP1_PUD_UP 2 +-#define RP1_PUD_KEEP 3 +- +-#endif /* __DT_BINDINGS_PINCTRL_RP1_H__ */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0877-serial-pl011-rp1-uart-support.patch b/target/linux/bcm27xx/patches-6.1/950-0877-serial-pl011-rp1-uart-support.patch new file mode 100644 index 0000000000..b0b9897e89 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0877-serial-pl011-rp1-uart-support.patch @@ -0,0 +1,129 @@ +From f88da9e21d8eff58eeb9280ae96bf9593121d8eb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 12 Oct 2022 13:24:51 +0100 +Subject: [PATCH] serial: pl011: rp1 uart support + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/amba-pl011.c | 96 +++++++++++++++++++++++++++++++++ + 1 file changed, 96 insertions(+) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -152,6 +152,20 @@ static const struct vendor_data vendor_s + .fixed_options = true, + }; + ++static struct vendor_data vendor_arm_axi = { ++ .reg_offset = pl011_std_offsets, ++ .ifls = UART011_IFLS_RX4_8 | UART011_IFLS_TX4_8, ++ .fr_busy = UART01x_FR_BUSY, ++ .fr_dsr = UART01x_FR_DSR, ++ .fr_cts = UART01x_FR_CTS, ++ .fr_ri = UART011_FR_RI, ++ .oversampling = false, ++ .dma_threshold = false, ++ .cts_event_workaround = false, ++ .always_enabled = false, ++ .fixed_options = false, ++}; ++ + #ifdef CONFIG_ACPI_SPCR_TABLE + static const struct vendor_data vendor_qdt_qdf2400_e44 = { + .reg_offset = pl011_std_offsets, +@@ -2972,6 +2986,86 @@ static struct platform_driver arm_sbsa_u + }, + }; + ++static int pl011_axi_probe(struct platform_device *pdev) ++{ ++ struct uart_amba_port *uap; ++ struct vendor_data *vendor = &vendor_arm_axi; ++ struct resource *r; ++ unsigned int periphid; ++ int portnr, ret, irq; ++ ++ portnr = pl011_find_free_port(); ++ if (portnr < 0) ++ return portnr; ++ ++ uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port), ++ GFP_KERNEL); ++ if (!uap) ++ return -ENOMEM; ++ ++ uap->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(uap->clk)) ++ return PTR_ERR(uap->clk); ++ ++ if (of_property_read_bool(pdev->dev.of_node, "cts-event-workaround")) { ++ vendor->cts_event_workaround = true; ++ dev_info(&pdev->dev, "cts_event_workaround enabled\n"); ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ periphid = 0x00241011; /* A safe default */ ++ of_property_read_u32(pdev->dev.of_node, "arm,primecell-periphid", ++ &periphid); ++ ++ uap->reg_offset = vendor->reg_offset; ++ uap->vendor = vendor; ++ uap->fifosize = (AMBA_REV_BITS(periphid) < 3) ? 16 : 32; ++ uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; ++ uap->port.irq = irq; ++ uap->port.ops = &amba_pl011_pops; ++ ++ snprintf(uap->type, sizeof(uap->type), "PL011 AXI"); ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ ret = pl011_setup_port(&pdev->dev, uap, r, portnr); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, uap); ++ ++ return pl011_register_port(uap); ++} ++ ++static int pl011_axi_remove(struct platform_device *pdev) ++{ ++ struct uart_amba_port *uap = platform_get_drvdata(pdev); ++ ++ uart_remove_one_port(&amba_reg, &uap->port); ++ pl011_unregister_port(uap); ++ return 0; ++} ++ ++static const struct of_device_id pl011_axi_of_match[] = { ++ { .compatible = "arm,pl011-axi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, pl011_axi_of_match); ++ ++static struct platform_driver pl011_axi_platform_driver = { ++ .probe = pl011_axi_probe, ++ .remove = pl011_axi_remove, ++ .driver = { ++ .name = "pl011-axi", ++ .pm = &pl011_dev_pm_ops, ++ .of_match_table = of_match_ptr(pl011_axi_of_match), ++ .suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011), ++ }, ++}; ++ + static const struct amba_id pl011_ids[] = { + { + .id = 0x00041011, +@@ -3005,6 +3099,8 @@ static int __init pl011_init(void) + + if (platform_driver_register(&arm_sbsa_uart_platform_driver)) + pr_warn("could not register SBSA UART platform driver\n"); ++ if (platform_driver_register(&pl011_axi_platform_driver)) ++ pr_warn("could not register PL011 AXI platform driver\n"); + return amba_driver_register(&pl011_driver); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch b/target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch new file mode 100644 index 0000000000..6bc21a6a57 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch @@ -0,0 +1,83 @@ +From 4a5ac516ca0a820e7c006ae408872009e37e114b Mon Sep 17 00:00:00 2001 +From: Liam Fraser +Date: Thu, 14 Mar 2019 16:01:26 +0000 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: define sdio timeout clocks + +Signed-off-by: Liam Fraser +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 12 ++++++++++++ + drivers/mmc/host/sdhci-pltfm.c | 8 ++++++++ + drivers/mmc/host/sdhci-pltfm.h | 3 +++ + 3 files changed, 23 insertions(+) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -330,6 +330,7 @@ static const struct sdhci_ops sdhci_dwcm + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, + .get_max_clock = dwcmshc_get_max_clock, ++ .get_timeout_clock = sdhci_pltfm_clk_get_timeout_clock, + .reset = sdhci_reset, + .adma_write_desc = dwcmshc_adma_write_desc, + }; +@@ -500,6 +501,16 @@ static int dwcmshc_probe(struct platform + clk_prepare_enable(priv->bus_clk); + } + ++ pltfm_host->timeout_clk = devm_clk_get(&pdev->dev, "timeout"); ++ if (IS_ERR(pltfm_host->timeout_clk)) { ++ err = PTR_ERR(pltfm_host->timeout_clk); ++ dev_err(&pdev->dev, "failed to get timeout clk: %d\n", err); ++ goto free_pltfm; ++ } ++ err = clk_prepare_enable(pltfm_host->timeout_clk); ++ if (err) ++ goto free_pltfm; ++ + err = mmc_of_parse(host->mmc); + if (err) + goto err_clk; +@@ -550,6 +561,7 @@ err_setup_host: + sdhci_cleanup_host(host); + err_clk: + clk_disable_unprepare(pltfm_host->clk); ++ clk_disable_unprepare(pltfm_host->timeout_clk); + clk_disable_unprepare(priv->bus_clk); + if (rk_priv) + clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, +--- a/drivers/mmc/host/sdhci-pltfm.c ++++ b/drivers/mmc/host/sdhci-pltfm.c +@@ -33,6 +33,14 @@ unsigned int sdhci_pltfm_clk_get_max_clo + } + EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock); + ++unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ ++ return clk_get_rate(pltfm_host->timeout_clk); ++} ++EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_timeout_clock); ++ + static const struct sdhci_ops sdhci_pltfm_ops = { + .set_clock = sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, +--- a/drivers/mmc/host/sdhci-pltfm.h ++++ b/drivers/mmc/host/sdhci-pltfm.h +@@ -20,6 +20,7 @@ struct sdhci_pltfm_data { + + struct sdhci_pltfm_host { + struct clk *clk; ++ struct clk *timeout_clk; + + /* migrate from sdhci_of_host */ + unsigned int clock; +@@ -106,6 +107,8 @@ extern int sdhci_pltfm_unregister(struct + + extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); + ++extern unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host); ++ + static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) + { + return host->private; diff --git a/target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch b/target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch new file mode 100644 index 0000000000..12d614fd94 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch @@ -0,0 +1,83 @@ +From 14a43b3fd43bf9b230f93d1eba276d40aac969ba Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 12 Oct 2022 14:07:32 +0100 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: rp1 sdio changes + +Signed-off-by: Phil Elwell +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 29 ++++++++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -87,6 +87,7 @@ struct rk35xx_priv { + + struct dwcmshc_priv { + struct clk *bus_clk; ++ struct clk *sdio_clk; + int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */ + void *priv; /* pointer to SoC private stuff */ + }; +@@ -114,6 +115,17 @@ static void dwcmshc_adma_write_desc(stru + sdhci_adma_write_desc(host, desc, addr, len, cmd); + } + ++static void dwcmshc_set_clock(struct sdhci_host *host, unsigned int clock) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ ++ if (priv->sdio_clk) ++ clk_set_rate(priv->sdio_clk, clock); ++ ++ sdhci_set_clock(host, clock); ++} ++ + static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +@@ -326,7 +338,7 @@ static void rk35xx_sdhci_reset(struct sd + } + + static const struct sdhci_ops sdhci_dwcmshc_ops = { +- .set_clock = sdhci_set_clock, ++ .set_clock = dwcmshc_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, + .get_max_clock = dwcmshc_get_max_clock, +@@ -346,8 +358,10 @@ static const struct sdhci_ops sdhci_dwcm + + static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { + .ops = &sdhci_dwcmshc_ops, +- .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, +- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, ++ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | ++ SDHCI_QUIRK_BROKEN_CARD_DETECTION, ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | ++ SDHCI_QUIRK2_BROKEN_HS200, + }; + + #ifdef CONFIG_ACPI +@@ -499,6 +513,14 @@ static int dwcmshc_probe(struct platform + priv->bus_clk = devm_clk_get(dev, "bus"); + if (!IS_ERR(priv->bus_clk)) + clk_prepare_enable(priv->bus_clk); ++ ++ pltfm_host->timeout_clk = devm_clk_get(dev, "timeout"); ++ if (!IS_ERR(pltfm_host->timeout_clk)) ++ err = clk_prepare_enable(pltfm_host->timeout_clk); ++ if (err) ++ goto free_pltfm; ++ ++ priv->sdio_clk = devm_clk_get_optional(&pdev->dev, "sdio"); + } + + pltfm_host->timeout_clk = devm_clk_get(&pdev->dev, "timeout"); +@@ -516,6 +538,7 @@ static int dwcmshc_probe(struct platform + goto err_clk; + + sdhci_get_of_property(pdev); ++ sdhci_enable_v4_mode(host); + + priv->vendor_specific_area1 = + sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK; diff --git a/target/linux/bcm27xx/patches-6.1/950-0880-clk-rp1-Add-sdio-clk-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0880-clk-rp1-Add-sdio-clk-driver.patch new file mode 100644 index 0000000000..7db5202ae4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0880-clk-rp1-Add-sdio-clk-driver.patch @@ -0,0 +1,641 @@ +From b427cc1a83404f48b12dec2efbef076b38df6218 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 12 Oct 2022 14:20:07 +0100 +Subject: [PATCH] clk: rp1: Add sdio-clk driver + +Signed-off-by: Phil Elwell +--- + drivers/clk/Kconfig | 6 + + drivers/clk/Makefile | 1 + + drivers/clk/clk-rp1-sdio.c | 600 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 607 insertions(+) + create mode 100644 drivers/clk/clk-rp1-sdio.c + +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -96,6 +96,12 @@ config COMMON_CLK_RP1 + help + Enable common clock framework support for Raspberry Pi RP1 + ++config COMMON_CLK_RP1_SDIO ++ tristate "Clock driver for the RP1 SDIO interfaces" ++ depends on MFD_RP1 ++ help ++ SDIO clock driver for the RP1 support chip ++ + config COMMON_CLK_HI655X + tristate "Clock driver for Hi655x" if EXPERT + depends on (MFD_HI655X_PMIC || COMPILE_TEST) +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -59,6 +59,7 @@ obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm + obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o + obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o + obj-$(CONFIG_COMMON_CLK_RP1) += clk-rp1.o ++obj-$(CONFIG_COMMON_CLK_RP1_SDIO) += clk-rp1-sdio.o + obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o + obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o + obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o +--- /dev/null ++++ b/drivers/clk/clk-rp1-sdio.c +@@ -0,0 +1,600 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * SDIO clock driver for RP1 ++ * ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++// Register : MODE ++#define MODE 0x00000000 ++#define MODE_BITS 0x70030000 ++#define MODE_RESET 0x00000000 ++// Field : MODE_STEPS_PER_CYCLE ++#define MODE_STEPS_PER_CYCLE_RESET 0x0 ++#define MODE_STEPS_PER_CYCLE_BITS 0x70000000 ++#define MODE_STEPS_PER_CYCLE_MSB 30 ++#define MODE_STEPS_PER_CYCLE_LSB 28 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_20 0x0 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_10 0x1 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_16 0x2 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_8 0x3 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_12 0x4 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_6 0x5 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_5 0x6 ++#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_4 0x7 ++// Field : MODE_SRC_SEL ++#define MODE_SRC_SEL_RESET 0x0 ++#define MODE_SRC_SEL_BITS 0x00030000 ++#define MODE_SRC_SEL_MSB 17 ++#define MODE_SRC_SEL_LSB 16 ++#define MODE_SRC_SEL_VALUE_STOP 0x0 ++#define MODE_SRC_SEL_VALUE_CLK_ALT_SRC 0x1 ++#define MODE_SRC_SEL_VALUE_PLL_SYS_VCO 0x2 ++#define MODE_SRC_SEL_VALUE_PLL_SYS_VCO_AGAIN 0x3 ++// Register : FROMIP ++#define FROMIP 0x00000004 ++#define FROMIP_BITS 0x0f9713ff ++#define FROMIP_RESET 0x00000000 ++// Field : FROMIP_TUNING_CCLK_SEL ++#define FROMIP_TUNING_CCLK_SEL_RESET 0x0 ++#define FROMIP_TUNING_CCLK_SEL_BITS 0x0f000000 ++#define FROMIP_TUNING_CCLK_SEL_MSB 27 ++#define FROMIP_TUNING_CCLK_SEL_LSB 24 ++// Field : FROMIP_TUNING_CCLK_UPDATE ++#define FROMIP_TUNING_CCLK_UPDATE_RESET 0x0 ++#define FROMIP_TUNING_CCLK_UPDATE_BITS 0x00800000 ++#define FROMIP_TUNING_CCLK_UPDATE_MSB 23 ++#define FROMIP_TUNING_CCLK_UPDATE_LSB 23 ++// Field : FROMIP_SAMPLE_CCLK_SEL ++#define FROMIP_SAMPLE_CCLK_SEL_RESET 0x0 ++#define FROMIP_SAMPLE_CCLK_SEL_BITS 0x00100000 ++#define FROMIP_SAMPLE_CCLK_SEL_MSB 20 ++#define FROMIP_SAMPLE_CCLK_SEL_LSB 20 ++// Field : FROMIP_CLK2CARD_ON ++#define FROMIP_CLK2CARD_ON_RESET 0x0 ++#define FROMIP_CLK2CARD_ON_BITS 0x00040000 ++#define FROMIP_CLK2CARD_ON_MSB 18 ++#define FROMIP_CLK2CARD_ON_LSB 18 ++// Field : FROMIP_CARD_CLK_STABLE ++#define FROMIP_CARD_CLK_STABLE_RESET 0x0 ++#define FROMIP_CARD_CLK_STABLE_BITS 0x00020000 ++#define FROMIP_CARD_CLK_STABLE_MSB 17 ++#define FROMIP_CARD_CLK_STABLE_LSB 17 ++// Field : FROMIP_CARD_CLK_EN ++#define FROMIP_CARD_CLK_EN_RESET 0x0 ++#define FROMIP_CARD_CLK_EN_BITS 0x00010000 ++#define FROMIP_CARD_CLK_EN_MSB 16 ++#define FROMIP_CARD_CLK_EN_LSB 16 ++// Field : FROMIP_CLK_GEN_SEL ++#define FROMIP_CLK_GEN_SEL_RESET 0x0 ++#define FROMIP_CLK_GEN_SEL_BITS 0x00001000 ++#define FROMIP_CLK_GEN_SEL_MSB 12 ++#define FROMIP_CLK_GEN_SEL_LSB 12 ++// Field : FROMIP_FREQ_SEL ++#define FROMIP_FREQ_SEL_RESET 0x000 ++#define FROMIP_FREQ_SEL_BITS 0x000003ff ++#define FROMIP_FREQ_SEL_MSB 9 ++#define FROMIP_FREQ_SEL_LSB 0 ++// Register : LOCAL ++#define LOCAL 0x00000008 ++#define LOCAL_BITS 0x1f9713ff ++#define LOCAL_RESET 0x00000000 ++// Field : LOCAL_TUNING_CCLK_SEL ++#define LOCAL_TUNING_CCLK_SEL_RESET 0x00 ++#define LOCAL_TUNING_CCLK_SEL_BITS 0x1f000000 ++#define LOCAL_TUNING_CCLK_SEL_MSB 28 ++#define LOCAL_TUNING_CCLK_SEL_LSB 24 ++// Field : LOCAL_TUNING_CCLK_UPDATE ++#define LOCAL_TUNING_CCLK_UPDATE_RESET 0x0 ++#define LOCAL_TUNING_CCLK_UPDATE_BITS 0x00800000 ++#define LOCAL_TUNING_CCLK_UPDATE_MSB 23 ++#define LOCAL_TUNING_CCLK_UPDATE_LSB 23 ++// Field : LOCAL_SAMPLE_CCLK_SEL ++#define LOCAL_SAMPLE_CCLK_SEL_RESET 0x0 ++#define LOCAL_SAMPLE_CCLK_SEL_BITS 0x00100000 ++#define LOCAL_SAMPLE_CCLK_SEL_MSB 20 ++#define LOCAL_SAMPLE_CCLK_SEL_LSB 20 ++// Field : LOCAL_CLK2CARD_ON ++#define LOCAL_CLK2CARD_ON_RESET 0x0 ++#define LOCAL_CLK2CARD_ON_BITS 0x00040000 ++#define LOCAL_CLK2CARD_ON_MSB 18 ++#define LOCAL_CLK2CARD_ON_LSB 18 ++// Field : LOCAL_CARD_CLK_STABLE ++#define LOCAL_CARD_CLK_STABLE_RESET 0x0 ++#define LOCAL_CARD_CLK_STABLE_BITS 0x00020000 ++#define LOCAL_CARD_CLK_STABLE_MSB 17 ++#define LOCAL_CARD_CLK_STABLE_LSB 17 ++// Field : LOCAL_CARD_CLK_EN ++#define LOCAL_CARD_CLK_EN_RESET 0x0 ++#define LOCAL_CARD_CLK_EN_BITS 0x00010000 ++#define LOCAL_CARD_CLK_EN_MSB 16 ++#define LOCAL_CARD_CLK_EN_LSB 16 ++// Field : LOCAL_CLK_GEN_SEL ++#define LOCAL_CLK_GEN_SEL_RESET 0x0 ++#define LOCAL_CLK_GEN_SEL_BITS 0x00001000 ++#define LOCAL_CLK_GEN_SEL_MSB 12 ++#define LOCAL_CLK_GEN_SEL_LSB 12 ++#define LOCAL_CLK_GEN_SEL_VALUE_PROGCLOCKMODE 0x0 ++#define LOCAL_CLK_GEN_SEL_VALUE_DIVCLOCKMODE 0x1 ++// Field : LOCAL_FREQ_SEL ++#define LOCAL_FREQ_SEL_RESET 0x000 ++#define LOCAL_FREQ_SEL_BITS 0x000003ff ++#define LOCAL_FREQ_SEL_MSB 9 ++#define LOCAL_FREQ_SEL_LSB 0 ++// Register : USE_LOCAL ++#define USE_LOCAL 0x0000000c ++#define USE_LOCAL_BITS 0x01951001 ++#define USE_LOCAL_RESET 0x00000000 ++// Field : USE_LOCAL_TUNING_CCLK_SEL ++#define USE_LOCAL_TUNING_CCLK_SEL_RESET 0x0 ++#define USE_LOCAL_TUNING_CCLK_SEL_BITS 0x01000000 ++#define USE_LOCAL_TUNING_CCLK_SEL_MSB 24 ++#define USE_LOCAL_TUNING_CCLK_SEL_LSB 24 ++// Field : USE_LOCAL_TUNING_CCLK_UPDATE ++#define USE_LOCAL_TUNING_CCLK_UPDATE_RESET 0x0 ++#define USE_LOCAL_TUNING_CCLK_UPDATE_BITS 0x00800000 ++#define USE_LOCAL_TUNING_CCLK_UPDATE_MSB 23 ++#define USE_LOCAL_TUNING_CCLK_UPDATE_LSB 23 ++// Field : USE_LOCAL_SAMPLE_CCLK_SEL ++#define USE_LOCAL_SAMPLE_CCLK_SEL_RESET 0x0 ++#define USE_LOCAL_SAMPLE_CCLK_SEL_BITS 0x00100000 ++#define USE_LOCAL_SAMPLE_CCLK_SEL_MSB 20 ++#define USE_LOCAL_SAMPLE_CCLK_SEL_LSB 20 ++// Field : USE_LOCAL_CLK2CARD_ON ++#define USE_LOCAL_CLK2CARD_ON_RESET 0x0 ++#define USE_LOCAL_CLK2CARD_ON_BITS 0x00040000 ++#define USE_LOCAL_CLK2CARD_ON_MSB 18 ++#define USE_LOCAL_CLK2CARD_ON_LSB 18 ++// Field : USE_LOCAL_CARD_CLK_EN ++#define USE_LOCAL_CARD_CLK_EN_RESET 0x0 ++#define USE_LOCAL_CARD_CLK_EN_BITS 0x00010000 ++#define USE_LOCAL_CARD_CLK_EN_MSB 16 ++#define USE_LOCAL_CARD_CLK_EN_LSB 16 ++// Field : USE_LOCAL_CLK_GEN_SEL ++#define USE_LOCAL_CLK_GEN_SEL_RESET 0x0 ++#define USE_LOCAL_CLK_GEN_SEL_BITS 0x00001000 ++#define USE_LOCAL_CLK_GEN_SEL_MSB 12 ++#define USE_LOCAL_CLK_GEN_SEL_LSB 12 ++// Field : USE_LOCAL_FREQ_SEL ++#define USE_LOCAL_FREQ_SEL_RESET 0x0 ++#define USE_LOCAL_FREQ_SEL_BITS 0x00000001 ++#define USE_LOCAL_FREQ_SEL_MSB 0 ++#define USE_LOCAL_FREQ_SEL_LSB 0 ++// Register : SD_DELAY ++#define SD_DELAY 0x00000010 ++#define SD_DELAY_BITS 0x0000001f ++#define SD_DELAY_RESET 0x00000000 ++// Field : SD_DELAY_STEPS ++#define SD_DELAY_STEPS_RESET 0x00 ++#define SD_DELAY_STEPS_BITS 0x0000001f ++#define SD_DELAY_STEPS_MSB 4 ++#define SD_DELAY_STEPS_LSB 0 ++// Register : RX_DELAY ++#define RX_DELAY 0x00000014 ++#define RX_DELAY_BITS 0x19f3331f ++#define RX_DELAY_RESET 0x00000000 ++// Field : RX_DELAY_BYPASS ++#define RX_DELAY_BYPASS_RESET 0x0 ++#define RX_DELAY_BYPASS_BITS 0x10000000 ++#define RX_DELAY_BYPASS_MSB 28 ++#define RX_DELAY_BYPASS_LSB 28 ++// Field : RX_DELAY_FAIL_ACTUAL ++#define RX_DELAY_FAIL_ACTUAL_RESET 0x0 ++#define RX_DELAY_FAIL_ACTUAL_BITS 0x08000000 ++#define RX_DELAY_FAIL_ACTUAL_MSB 27 ++#define RX_DELAY_FAIL_ACTUAL_LSB 27 ++// Field : RX_DELAY_ACTUAL ++#define RX_DELAY_ACTUAL_RESET 0x00 ++#define RX_DELAY_ACTUAL_BITS 0x01f00000 ++#define RX_DELAY_ACTUAL_MSB 24 ++#define RX_DELAY_ACTUAL_LSB 20 ++// Field : RX_DELAY_OFFSET ++#define RX_DELAY_OFFSET_RESET 0x0 ++#define RX_DELAY_OFFSET_BITS 0x00030000 ++#define RX_DELAY_OFFSET_MSB 17 ++#define RX_DELAY_OFFSET_LSB 16 ++// Field : RX_DELAY_OVERFLOW ++#define RX_DELAY_OVERFLOW_RESET 0x0 ++#define RX_DELAY_OVERFLOW_BITS 0x00003000 ++#define RX_DELAY_OVERFLOW_MSB 13 ++#define RX_DELAY_OVERFLOW_LSB 12 ++#define RX_DELAY_OVERFLOW_VALUE_ALLOW 0x0 ++#define RX_DELAY_OVERFLOW_VALUE_CLAMP 0x1 ++#define RX_DELAY_OVERFLOW_VALUE_FAIL 0x2 ++// Field : RX_DELAY_MAP ++#define RX_DELAY_MAP_RESET 0x0 ++#define RX_DELAY_MAP_BITS 0x00000300 ++#define RX_DELAY_MAP_MSB 9 ++#define RX_DELAY_MAP_LSB 8 ++#define RX_DELAY_MAP_VALUE_DIRECT 0x0 ++#define RX_DELAY_MAP_VALUE 0x1 ++#define RX_DELAY_MAP_VALUE_STRETCH 0x2 ++// Field : RX_DELAY_FIXED ++#define RX_DELAY_FIXED_RESET 0x00 ++#define RX_DELAY_FIXED_BITS 0x0000001f ++#define RX_DELAY_FIXED_MSB 4 ++#define RX_DELAY_FIXED_LSB 0 ++// Register : NDIV ++#define NDIV 0x00000018 ++#define NDIV_BITS 0x1fff0000 ++#define NDIV_RESET 0x00110000 ++// Field : NDIV_DIVB ++#define NDIV_DIVB_RESET 0x001 ++#define NDIV_DIVB_BITS 0x1ff00000 ++#define NDIV_DIVB_MSB 28 ++#define NDIV_DIVB_LSB 20 ++// Field : NDIV_DIVA ++#define NDIV_DIVA_RESET 0x1 ++#define NDIV_DIVA_BITS 0x000f0000 ++#define NDIV_DIVA_MSB 19 ++#define NDIV_DIVA_LSB 16 ++// Register : CS ++#define CS 0x0000001c ++#define CS_BITS 0x00111101 ++#define CS_RESET 0x00000001 ++// Field : CS_RX_DEL_UPDATED ++#define CS_RX_DEL_UPDATED_RESET 0x0 ++#define CS_RX_DEL_UPDATED_BITS 0x00100000 ++#define CS_RX_DEL_UPDATED_MSB 20 ++#define CS_RX_DEL_UPDATED_LSB 20 ++// Field : CS_RX_CLK_RUNNING ++#define CS_RX_CLK_RUNNING_RESET 0x0 ++#define CS_RX_CLK_RUNNING_BITS 0x00010000 ++#define CS_RX_CLK_RUNNING_MSB 16 ++#define CS_RX_CLK_RUNNING_LSB 16 ++// Field : CS_SD_CLK_RUNNING ++#define CS_SD_CLK_RUNNING_RESET 0x0 ++#define CS_SD_CLK_RUNNING_BITS 0x00001000 ++#define CS_SD_CLK_RUNNING_MSB 12 ++#define CS_SD_CLK_RUNNING_LSB 12 ++// Field : CS_TX_CLK_RUNNING ++#define CS_TX_CLK_RUNNING_RESET 0x0 ++#define CS_TX_CLK_RUNNING_BITS 0x00000100 ++#define CS_TX_CLK_RUNNING_MSB 8 ++#define CS_TX_CLK_RUNNING_LSB 8 ++// Field : CS_RESET ++#define CS_RESET_RESET 0x1 ++#define CS_RESET_BITS 0x00000001 ++#define CS_RESET_MSB 0 ++#define CS_RESET_LSB 0 ++ ++#define FPGA_SRC_RATE 400000000 ++ ++/* Base number of steps to delay in relation to tx clk. ++ * The relationship of the 3 clocks are as follows: ++ * tx_clk: This clock is provided to the controller. Data is sent out ++ * to the pads using this clock. ++ * sd_clk: This clock is sent out to the card. ++ * rx_clk: This clock is used to sample the data coming back from the card. ++ * This may need to be several steps ahead of the tx_clk. The default rx delay ++ * is used as a base delay, and can be further adjusted by the sd host ++ * controller during the tuning process if using a DDR50 or faster SD card ++ */ ++/* ++ * PRJY-1813 - the default SD clock delay needs to be set to ~60% of the total ++ * number of steps to meet tISU (>6ns) and tIH (>2ns) in high-speed mode. ++ * On FPGA this means delay SDCLK by 5, and sample RX with a delay of 6. ++ */ ++#define DEFAULT_RX_DELAY 6 ++#define DEFAULT_SD_DELAY 5 ++ ++struct rp1_sdio_clkgen { ++ struct device *dev; ++ ++ /* Source clock. Either PLL VCO or fixed freq on FPGA */ ++ struct clk *src_clk; ++ /* Desired base frequency. Max freq card can go */ ++ struct clk *base_clk; ++ ++ struct clk_hw hw; ++ void __iomem *regs; ++ ++ /* Starting value of local register before changing freq */ ++ u32 local_base; ++}; ++ ++static inline void clkgen_write(struct rp1_sdio_clkgen *clkgen, u32 reg, u32 val) ++{ ++ dev_dbg(clkgen->dev, "%s: write reg 0x%x: 0x%x\n", __func__, reg, val); ++ writel(val, clkgen->regs + reg); ++} ++ ++static inline u32 clkgen_read(struct rp1_sdio_clkgen *clkgen, u32 reg) ++{ ++ u32 val = readl(clkgen->regs + reg); ++ ++ dev_dbg(clkgen->dev, "%s: read reg 0x%x: 0x%x\n", __func__, reg, val); ++ return val; ++} ++ ++static int get_steps(unsigned int steps) ++{ ++ int ret = -1; ++ ++ if (steps == 4) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_4; ++ else if (steps == 5) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_5; ++ else if (steps == 6) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_6; ++ else if (steps == 8) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_8; ++ else if (steps == 10) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_10; ++ else if (steps == 12) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_12; ++ else if (steps == 16) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_16; ++ else if (steps == 20) ++ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_20; ++ return ret; ++} ++ ++static int rp1_sdio_clk_init(struct rp1_sdio_clkgen *clkgen) ++{ ++ unsigned long src_rate = clk_get_rate(clkgen->src_clk); ++ unsigned long base_rate = clk_get_rate(clkgen->base_clk); ++ unsigned int steps = src_rate / base_rate; ++ u32 reg = 0; ++ int steps_value = 0; ++ ++ dev_dbg(clkgen->dev, "init: src_rate %lu, base_rate %lu, steps %d\n", ++ src_rate, base_rate, steps); ++ ++ /* Assert reset while we set up clkgen */ ++ clkgen_write(clkgen, CS, CS_RESET_BITS); ++ ++ /* Pick clock source */ ++ if (src_rate == FPGA_SRC_RATE) { ++ /* Using ALT SRC */ ++ reg |= MODE_SRC_SEL_VALUE_CLK_ALT_SRC << MODE_SRC_SEL_LSB; ++ } else { ++ /* Assume we are using PLL SYS VCO */ ++ reg |= MODE_SRC_SEL_VALUE_PLL_SYS_VCO << MODE_SRC_SEL_LSB; ++ } ++ ++ /* How many delay steps are available in one cycle for this source */ ++ steps_value = get_steps(steps); ++ if (steps_value < 0) { ++ dev_err(clkgen->dev, "Invalid step value: %d\n", steps); ++ return -EINVAL; ++ } ++ reg |= steps_value << MODE_STEPS_PER_CYCLE_LSB; ++ ++ /* Mode register is done now*/ ++ clkgen_write(clkgen, MODE, reg); ++ ++ /* Now set delay mode */ ++ /* Clamp value if out of range rx delay is used */ ++ reg = RX_DELAY_OVERFLOW_VALUE_CLAMP << RX_DELAY_OVERFLOW_LSB; ++ /* SD tuning bus goes from 0x0 to 0xf but we don't necessarily have that ++ * many steps available depending on the source so map 0x0 -> 0xf to one ++ * cycle of rx delay ++ */ ++ reg |= RX_DELAY_MAP_VALUE_STRETCH << RX_DELAY_MAP_LSB; ++ ++ /* Default RX delay */ ++ dev_dbg(clkgen->dev, "default rx delay %d\n", DEFAULT_RX_DELAY); ++ reg |= (DEFAULT_RX_DELAY & RX_DELAY_FIXED_BITS) << RX_DELAY_FIXED_LSB; ++ clkgen_write(clkgen, RX_DELAY, reg); ++ ++ /* Default SD delay */ ++ dev_dbg(clkgen->dev, "default sd delay %d\n", DEFAULT_SD_DELAY); ++ reg = (DEFAULT_SD_DELAY & SD_DELAY_STEPS_BITS) << SD_DELAY_STEPS_LSB; ++ clkgen_write(clkgen, SD_DELAY, reg); ++ ++ /* We select freq, we turn on tx clock, we turn on sd clk, ++ * we pick clock generator mode ++ */ ++ reg = USE_LOCAL_FREQ_SEL_BITS | USE_LOCAL_CARD_CLK_EN_BITS | ++ USE_LOCAL_CLK2CARD_ON_BITS | USE_LOCAL_CLK_GEN_SEL_BITS; ++ clkgen_write(clkgen, USE_LOCAL, reg); ++ ++ /* Deassert reset. Reset bit is only writable bit of CS ++ * reg so fine to write a 0. ++ */ ++ clkgen_write(clkgen, CS, 0); ++ ++ return 0; ++} ++ ++#define RUNNING \ ++ (CS_TX_CLK_RUNNING_BITS | CS_RX_CLK_RUNNING_BITS | \ ++ CS_SD_CLK_RUNNING_BITS) ++static int rp1_sdio_clk_is_prepared(struct clk_hw *hw) ++{ ++ struct rp1_sdio_clkgen *clkgen = ++ container_of(hw, struct rp1_sdio_clkgen, hw); ++ u32 status; ++ ++ dev_dbg(clkgen->dev, "is_prepared\n"); ++ status = clkgen_read(clkgen, CS); ++ return ((status & RUNNING) == RUNNING); ++} ++ ++/* Can define an additional divider if an sd card isn't working at full speed */ ++/* #define SLOWDOWN 3 */ ++ ++static unsigned long rp1_sdio_clk_get_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ /* Get the current rate */ ++ struct rp1_sdio_clkgen *clkgen = ++ container_of(hw, struct rp1_sdio_clkgen, hw); ++ unsigned long actual_rate = 0; ++ u32 ndiv_diva; ++ u32 ndiv_divb; ++ u32 tmp; ++ u32 div; ++ ++ tmp = clkgen_read(clkgen, LOCAL); ++ if ((tmp & LOCAL_CLK2CARD_ON_BITS) == 0) { ++ dev_dbg(clkgen->dev, "get_rate 0\n"); ++ return 0; ++ } ++ ++ tmp = clkgen_read(clkgen, NDIV); ++ ndiv_diva = (tmp & NDIV_DIVA_BITS) >> NDIV_DIVA_LSB; ++ ndiv_divb = (tmp & NDIV_DIVB_BITS) >> NDIV_DIVB_LSB; ++ div = ndiv_diva * ndiv_divb; ++ actual_rate = (clk_get_rate(clkgen->base_clk) / div); ++ ++#ifdef SLOWDOWN ++ actual_rate *= SLOWDOWN; ++#endif ++ ++ dev_dbg(clkgen->dev, "get_rate. ndiv_diva %d, ndiv_divb %d = %lu\n", ++ ndiv_diva, ndiv_divb, actual_rate); ++ ++ return actual_rate; ++} ++ ++static int rp1_sdio_clk_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct rp1_sdio_clkgen *clkgen = ++ container_of(hw, struct rp1_sdio_clkgen, hw); ++ u32 div; ++ u32 reg; ++ ++ dev_dbg(clkgen->dev, "set_rate %lu\n", rate); ++ ++ if (rate == 0) { ++ /* Keep tx clock running */ ++ clkgen_write(clkgen, LOCAL, LOCAL_CARD_CLK_EN_BITS); ++ return 0; ++ } ++ ++#ifdef SLOWDOWN ++ rate /= SLOWDOWN; ++#endif ++ ++ div = (clk_get_rate(clkgen->base_clk) / rate) - 1; ++ reg = LOCAL_CLK_GEN_SEL_BITS | LOCAL_CARD_CLK_EN_BITS | ++ LOCAL_CLK2CARD_ON_BITS | (div << LOCAL_FREQ_SEL_LSB); ++ clkgen_write(clkgen, LOCAL, reg); ++ ++ return 0; ++} ++ ++#define MAX_NDIV (256 * 8) ++static int rp1_sdio_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ unsigned long rate; ++ struct rp1_sdio_clkgen *clkgen = ++ container_of(hw, struct rp1_sdio_clkgen, hw); ++ unsigned long base_rate = clk_get_rate(clkgen->base_clk); ++ u32 div; ++ ++ /* What is the actual rate I can get if I request xyz */ ++ if (req->rate) { ++ div = min((u32)(base_rate / req->rate), (u32)MAX_NDIV); ++ rate = base_rate / div; ++ req->rate = rate; ++ dev_dbg(clkgen->dev, "determine_rate %lu: %lu / %d = %lu\n", ++ req->rate, base_rate, div, rate); ++ } else { ++ rate = 0; ++ dev_dbg(clkgen->dev, "determine_rate %lu: %lu\n", req->rate, ++ rate); ++ } ++ ++ return 0; ++} ++ ++static const struct clk_ops rp1_sdio_clk_ops = { ++ .is_prepared = rp1_sdio_clk_is_prepared, ++ .recalc_rate = rp1_sdio_clk_get_rate, ++ .set_rate = rp1_sdio_clk_set_rate, ++ .determine_rate = rp1_sdio_clk_determine_rate, ++}; ++ ++static int rp1_sdio_clk_probe(struct platform_device *pdev) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ struct rp1_sdio_clkgen *clkgen; ++ void __iomem *regs; ++ struct clk_init_data init = {}; ++ int ret; ++ ++ clkgen = devm_kzalloc(&pdev->dev, sizeof(*clkgen), GFP_KERNEL); ++ if (!clkgen) ++ return -ENOMEM; ++ platform_set_drvdata(pdev, clkgen); ++ ++ clkgen->dev = &pdev->dev; ++ ++ /* Source freq */ ++ clkgen->src_clk = devm_clk_get(&pdev->dev, "src"); ++ if (IS_ERR(clkgen->src_clk)) { ++ int err = PTR_ERR(clkgen->src_clk); ++ ++ dev_err(&pdev->dev, "failed to get src clk: %d\n", err); ++ return err; ++ } ++ ++ /* Desired maximum output freq (i.e. base freq) */ ++ clkgen->base_clk = devm_clk_get(&pdev->dev, "base"); ++ if (IS_ERR(clkgen->base_clk)) { ++ int err = PTR_ERR(clkgen->base_clk); ++ ++ dev_err(&pdev->dev, "failed to get base clk: %d\n", err); ++ return err; ++ } ++ ++ regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(regs)) ++ return PTR_ERR(regs); ++ ++ init.name = node->name; ++ init.ops = &rp1_sdio_clk_ops; ++ init.flags = CLK_GET_RATE_NOCACHE; ++ ++ clkgen->hw.init = &init; ++ clkgen->regs = regs; ++ ++ dev_info(&pdev->dev, "loaded %s\n", init.name); ++ ++ ret = devm_clk_hw_register(&pdev->dev, &clkgen->hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &clkgen->hw); ++ if (ret) ++ return ret; ++ ++ ret = rp1_sdio_clk_init(clkgen); ++ return ret; ++} ++ ++static int rp1_sdio_clk_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id rp1_sdio_clk_dt_ids[] = { ++ { .compatible = "raspberrypi,rp1-sdio-clk", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rp1_sdio_clk_dt_ids); ++ ++static struct platform_driver rp1_sdio_clk_driver = { ++ .probe = rp1_sdio_clk_probe, ++ .remove = rp1_sdio_clk_remove, ++ .driver = { ++ .name = "rp1-sdio-clk", ++ .of_match_table = rp1_sdio_clk_dt_ids, ++ }, ++}; ++module_platform_driver(rp1_sdio_clk_driver); ++ ++MODULE_AUTHOR("Liam Fraser "); ++MODULE_DESCRIPTION("RP1 SDIO clock driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch b/target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch new file mode 100644 index 0000000000..ea3b315501 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch @@ -0,0 +1,76 @@ +From 50adadfaf324ed5cbb59ce2b85eda59de4e3801a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 4 Dec 2020 15:20:36 +0000 +Subject: [PATCH] i2c: designware: Add SMBUS quick command support + +The SMBUS emulation code turns an SMBUS quick command into a zero- +length read. This controller can't do zero length accesses, but it +can do quick commands, so reverse the emulation. The alternative +would be to properly implement the SMBUS support but that is a lot +more work, and unnecessary just to get i2cdetect working. + +Signed-off-by: Phil Elwell +--- + drivers/i2c/busses/i2c-designware-core.h | 2 ++ + drivers/i2c/busses/i2c-designware-master.c | 17 +++++++++++++++-- + 2 files changed, 17 insertions(+), 2 deletions(-) + +--- a/drivers/i2c/busses/i2c-designware-core.h ++++ b/drivers/i2c/busses/i2c-designware-core.h +@@ -117,7 +117,9 @@ + + #define DW_IC_ERR_TX_ABRT 0x1 + ++#define DW_IC_TAR_SPECIAL BIT(11) + #define DW_IC_TAR_10BITADDR_MASTER BIT(12) ++#define DW_IC_TAR_SMBUS_QUICK_CMD BIT(16) + + #define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3)) + #define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2) +--- a/drivers/i2c/busses/i2c-designware-master.c ++++ b/drivers/i2c/busses/i2c-designware-master.c +@@ -228,6 +228,10 @@ static void i2c_dw_xfer_init(struct dw_i + ic_tar = DW_IC_TAR_10BITADDR_MASTER; + } + ++ /* Convert a zero-length read into an SMBUS quick command */ ++ if (!msgs[dev->msg_write_idx].len) ++ ic_tar = DW_IC_TAR_SPECIAL | DW_IC_TAR_SMBUS_QUICK_CMD; ++ + regmap_update_bits(dev->map, DW_IC_CON, DW_IC_CON_10BITADDR_MASTER, + ic_con); + +@@ -409,6 +413,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) + regmap_read(dev->map, DW_IC_RXFLR, &flr); + rx_limit = dev->rx_fifo_depth - flr; + ++ /* Handle SMBUS quick commands */ ++ if (!buf_len) { ++ if (msgs[dev->msg_write_idx].flags & I2C_M_RD) ++ regmap_write(dev->map, DW_IC_DATA_CMD, 0x300); ++ else ++ regmap_write(dev->map, DW_IC_DATA_CMD, 0x200); ++ } ++ + while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { + u32 cmd = 0; + +@@ -673,7 +685,7 @@ static const struct i2c_algorithm i2c_dw + }; + + static const struct i2c_adapter_quirks i2c_dw_quirks = { +- .flags = I2C_AQ_NO_ZERO_LEN, ++ .flags = 0, + }; + + static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) +@@ -813,7 +825,8 @@ void i2c_dw_configure_master(struct dw_i + { + struct i2c_timings *t = &dev->timings; + +- dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY; ++ dev->functionality = I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_QUICK | ++ DW_IC_DEFAULT_FUNCTIONALITY; + + dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | + DW_IC_CON_RESTART_EN; diff --git a/target/linux/bcm27xx/patches-6.1/950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch b/target/linux/bcm27xx/patches-6.1/950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch new file mode 100644 index 0000000000..fff6cfdeb4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch @@ -0,0 +1,355 @@ +From 0a1cd70189daec3baf4b4a233dd8e25ffbb9d512 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 28 Apr 2021 17:46:01 +0100 +Subject: [PATCH] dmaengine: dw-axi-dmac: Fixes for RP1 + +Don't assume that DMA addresses of devices are the same as their +physical addresses - convert correctly. + +The CFG2 register layout is used when there are more than 8 channels, +but also when configured for more than 16 target peripheral devices +because the index of the handshake signal has to be made wider. + +Reset the DMAC on probe + +The driver goes to the trouble of tracking when transfers have been +paused, but then doesn't report that state when queried. + +Not having APB registers is not an error - for most use cases it's +not even of interest, it's expected. Demote the message to debug level, +which is disabled by default. + +Each channel has a descriptor pool, which is shared between transfers. +It is unsafe to treat the total number of descriptors allocated from a +pool as the number allocated to a specific transfer; doing so leads +to releasing buffers that shouldn't be released and walking off the +ends of descriptor lists. Instead, give each transfer descriptor its +own count. + +Support partial transfers: +Some use cases involve streaming from a device where the transfer only +proceeds when the device's FIFO occupancy exceeds a certain threshold. +In such cases (e.g. when pulling data from a UART) it is important to +know how much data has been transferred so far, in order that remaining +bytes can be read from the FIFO directly by software. + +Add the necessary code to provide this "residue" value with a finer, +sub-transfer granularity. + +In order to prevent the occasional byte getting stuck in the DMA +controller's internal buffers, restrict the destination memory width +to the source register width. + +Signed-off-by: Phil Elwell +--- + .../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 136 +++++++++++++++--- + drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 3 + + 2 files changed, 118 insertions(+), 21 deletions(-) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -79,6 +80,17 @@ axi_chan_iowrite64(struct axi_dma_chan * + iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4); + } + ++static inline u64 ++axi_chan_ioread64(struct axi_dma_chan *chan, u32 reg) ++{ ++ /* ++ * We split one 64 bit read into two 32 bit reads as some HW doesn't ++ * support 64 bit access. ++ */ ++ return ((u64)ioread32(chan->chan_regs + reg + 4) << 32) + ++ ioread32(chan->chan_regs + reg); ++} ++ + static inline void axi_chan_config_write(struct axi_dma_chan *chan, + struct axi_dma_chan_config *config) + { +@@ -86,7 +98,7 @@ static inline void axi_chan_config_write + + cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS | + config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS); +- if (chan->chip->dw->hdata->reg_map_8_channels) { ++ if (!chan->chip->dw->hdata->reg_map_cfg2) { + cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS | + config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS | + config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS | +@@ -214,7 +226,18 @@ static void axi_dma_hw_init(struct axi_d + { + int ret; + u32 i; ++ int retries = 1000; + ++ axi_dma_iowrite32(chip, DMAC_RESET, 1); ++ while (axi_dma_ioread32(chip, DMAC_RESET)) { ++ retries--; ++ if (!retries) { ++ dev_err(chip->dev, "%s: DMAC failed to reset\n", ++ __func__); ++ return; ++ } ++ cpu_relax(); ++ } + for (i = 0; i < chip->dw->hdata->nr_channels; i++) { + axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL); + axi_chan_disable(&chip->dw->chan[i]); +@@ -276,7 +299,7 @@ static struct axi_dma_lli *axi_desc_get( + static void axi_desc_put(struct axi_dma_desc *desc) + { + struct axi_dma_chan *chan = desc->chan; +- int count = atomic_read(&chan->descs_allocated); ++ u32 count = desc->hw_desc_count; + struct axi_dma_hw_desc *hw_desc; + int descs_put; + +@@ -298,6 +321,48 @@ static void vchan_desc_put(struct virt_d + axi_desc_put(vd_to_axi_desc(vdesc)); + } + ++static u32 axi_dma_desc_src_pos(struct axi_dma_desc *desc, dma_addr_t addr) ++{ ++ unsigned int idx = 0; ++ u32 pos = 0; ++ ++ while (pos < desc->length) { ++ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++]; ++ u32 len = hw_desc->len; ++ dma_addr_t start = le64_to_cpu(hw_desc->lli->sar); ++ ++ if (addr >= start && addr <= (start + len)) { ++ pos += addr - start; ++ break; ++ } ++ ++ pos += len; ++ } ++ ++ return pos; ++} ++ ++static u32 axi_dma_desc_dst_pos(struct axi_dma_desc *desc, dma_addr_t addr) ++{ ++ unsigned int idx = 0; ++ u32 pos = 0; ++ ++ while (pos < desc->length) { ++ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++]; ++ u32 len = hw_desc->len; ++ dma_addr_t start = le64_to_cpu(hw_desc->lli->dar); ++ ++ if (addr >= start && addr <= (start + len)) { ++ pos += addr - start; ++ break; ++ } ++ ++ pos += len; ++ } ++ ++ return pos; ++} ++ + static enum dma_status + dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, + struct dma_tx_state *txstate) +@@ -307,10 +372,7 @@ dma_chan_tx_status(struct dma_chan *dcha + enum dma_status status; + u32 completed_length; + unsigned long flags; +- u32 completed_blocks; + size_t bytes = 0; +- u32 length; +- u32 len; + + status = dma_cookie_status(dchan, cookie, txstate); + if (status == DMA_COMPLETE || !txstate) +@@ -319,16 +381,31 @@ dma_chan_tx_status(struct dma_chan *dcha + spin_lock_irqsave(&chan->vc.lock, flags); + + vdesc = vchan_find_desc(&chan->vc, cookie); +- if (vdesc) { +- length = vd_to_axi_desc(vdesc)->length; +- completed_blocks = vd_to_axi_desc(vdesc)->completed_blocks; +- len = vd_to_axi_desc(vdesc)->hw_desc[0].len; +- completed_length = completed_blocks * len; +- bytes = length - completed_length; ++ if (vdesc && vdesc == vchan_next_desc(&chan->vc)) { ++ /* This descriptor is in-progress */ ++ struct axi_dma_desc *desc = vd_to_axi_desc(vdesc); ++ dma_addr_t addr; ++ ++ if (chan->direction == DMA_MEM_TO_DEV) { ++ addr = axi_chan_ioread64(chan, CH_SAR); ++ completed_length = axi_dma_desc_src_pos(desc, addr); ++ } else if (chan->direction == DMA_DEV_TO_MEM) { ++ addr = axi_chan_ioread64(chan, CH_DAR); ++ completed_length = axi_dma_desc_dst_pos(desc, addr); ++ } else { ++ completed_length = 0; ++ } ++ bytes = desc->length - completed_length; ++ } else if (vdesc) { ++ /* Still in the queue so not started */ ++ bytes = vd_to_axi_desc(vdesc)->length; + } + +- spin_unlock_irqrestore(&chan->vc.lock, flags); ++ if (chan->is_paused && status == DMA_IN_PROGRESS) ++ status = DMA_PAUSED; ++ + dma_set_residue(txstate, bytes); ++ spin_unlock_irqrestore(&chan->vc.lock, flags); + + return status; + } +@@ -516,7 +593,7 @@ static void dw_axi_dma_set_hw_channel(st + unsigned long reg_value, val; + + if (!chip->apb_regs) { +- dev_err(chip->dev, "apb_regs not initialized\n"); ++ dev_dbg(chip->dev, "apb_regs not initialized\n"); + return; + } + +@@ -620,18 +697,25 @@ static int dw_axi_dma_set_hw_desc(struct + switch (chan->direction) { + case DMA_MEM_TO_DEV: + reg_width = __ffs(chan->config.dst_addr_width); +- device_addr = chan->config.dst_addr; ++ 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 | + 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_width = __ffs(chan->config.src_addr_width); +- device_addr = chan->config.src_addr; ++ /* 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 | + 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; +@@ -667,9 +751,6 @@ static int dw_axi_dma_set_hw_desc(struct + } + + hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1); +- +- ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | +- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS; + hw_desc->lli->ctl_lo = cpu_to_le32(ctllo); + + set_desc_src_master(hw_desc); +@@ -764,6 +845,8 @@ dw_axi_dma_chan_prep_cyclic(struct dma_c + src_addr += segment_len; + } + ++ desc->hw_desc_count = total_segments; ++ + llp = desc->hw_desc[0].llp; + + /* Managed transfer list */ +@@ -843,6 +926,8 @@ dw_axi_dma_chan_prep_slave_sg(struct dma + } while (len >= segment_len); + } + ++ desc->hw_desc_count = loop; ++ + /* Set end-of-link to the last link descriptor of list */ + set_desc_last(&desc->hw_desc[num_sgs - 1]); + +@@ -950,6 +1035,8 @@ dma_chan_prep_dma_memcpy(struct dma_chan + num++; + } + ++ desc->hw_desc_count = num; ++ + /* Set end-of-link to the last link descriptor of list */ + set_desc_last(&desc->hw_desc[num - 1]); + /* Managed transfer list */ +@@ -998,7 +1085,7 @@ static void axi_chan_dump_lli(struct axi + static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, + struct axi_dma_desc *desc_head) + { +- int count = atomic_read(&chan->descs_allocated); ++ u32 count = desc_head->hw_desc_count; + int i; + + for (i = 0; i < count; i++) +@@ -1041,11 +1128,11 @@ out: + + static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan) + { +- int count = atomic_read(&chan->descs_allocated); + struct axi_dma_hw_desc *hw_desc; + struct axi_dma_desc *desc; + struct virt_dma_desc *vd; + unsigned long flags; ++ u32 count; + u64 llp; + int i; + +@@ -1067,6 +1154,7 @@ static void axi_chan_block_xfer_complete + if (chan->cyclic) { + desc = vd_to_axi_desc(vd); + if (desc) { ++ count = desc->hw_desc_count; + llp = lo_hi_readq(chan->chan_regs + CH_LLP); + for (i = 0; i < count; i++) { + hw_desc = &desc->hw_desc[i]; +@@ -1310,6 +1398,8 @@ static int parse_device_properties(struc + chip->dw->hdata->nr_channels = tmp; + if (tmp <= DMA_REG_MAP_CH_REF) + chip->dw->hdata->reg_map_8_channels = true; ++ else ++ chip->dw->hdata->reg_map_cfg2 = true; + + ret = device_property_read_u32(dev, "snps,dma-masters", &tmp); + if (ret) +@@ -1319,6 +1409,10 @@ static int parse_device_properties(struc + + chip->dw->hdata->nr_masters = tmp; + ++ ret = device_property_read_u32(dev, "snps,dma-targets", &tmp); ++ if (!ret && tmp > 16) ++ chip->dw->hdata->reg_map_cfg2 = true; ++ + ret = device_property_read_u32(dev, "snps,data-width", &tmp); + if (ret) + return ret; +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +@@ -32,6 +32,8 @@ struct dw_axi_dma_hcfg { + u32 axi_rw_burst_len; + /* Register map for DMAX_NUM_CHANNELS <= 8 */ + bool reg_map_8_channels; ++ /* Register map for DMAX_NUM_CHANNELS > 8 || DMAX_NUM_HS_IF > 16*/ ++ bool reg_map_cfg2; + bool restrict_axi_burst_len; + }; + +@@ -100,6 +102,7 @@ struct axi_dma_desc { + + struct virt_dma_desc vd; + struct axi_dma_chan *chan; ++ u32 hw_desc_count; + u32 completed_blocks; + u32 length; + u32 period_len; diff --git a/target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch b/target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch new file mode 100644 index 0000000000..68eca7961f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch @@ -0,0 +1,64 @@ +From 8a9c0607ce0daa91c48faefd70ea73bda54ed0ae Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 29 Nov 2022 10:09:54 +0000 +Subject: [PATCH] spi: dw: Handle combined tx and rx messages + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-dw-core.c | 12 +++++++++--- + drivers/spi/spi-dw-mmio.c | 8 ++++++-- + 2 files changed, 15 insertions(+), 5 deletions(-) + +--- a/drivers/spi/spi-dw-core.c ++++ b/drivers/spi/spi-dw-core.c +@@ -244,8 +244,11 @@ static irqreturn_t dw_spi_transfer_handl + */ + 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->master); ++ } + } + + return IRQ_HANDLED; +@@ -372,8 +375,11 @@ static void dw_spi_irq_setup(struct dw_s + + dws->transfer_handler = dw_spi_transfer_handler; + +- imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI | +- DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI; ++ imask = 0; ++ if (dws->tx_len) ++ 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); + } + +--- a/drivers/spi/spi-dw-mmio.c ++++ b/drivers/spi/spi-dw-mmio.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include "spi-dw.h" + +@@ -280,8 +281,11 @@ static int dw_spi_mmio_probe(struct plat + dws->paddr = mem->start; + + dws->irq = platform_get_irq(pdev, 0); +- if (dws->irq < 0) +- return dws->irq; /* -ENXIO */ ++ if (dws->irq < 0) { ++ if (dws->irq != -ENXIO) ++ return dws->irq; /* -ENXIO */ ++ dws->irq = IRQ_NOTCONNECTED; ++ } + + dwsmmio->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(dwsmmio->clk)) diff --git a/target/linux/bcm27xx/patches-6.1/950-0884-pwm-Add-support-for-RP1-PWM.patch b/target/linux/bcm27xx/patches-6.1/950-0884-pwm-Add-support-for-RP1-PWM.patch new file mode 100644 index 0000000000..241d6c49db --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0884-pwm-Add-support-for-RP1-PWM.patch @@ -0,0 +1,292 @@ +From 824f18efc8ad59e2783570ae2df83e2cd16b9f04 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 14 Feb 2023 14:03:54 +0000 +Subject: [PATCH] pwm: Add support for RP1 PWM + +Add a driver for the RP1 PWM block. + +Signed-off-by: Phil Elwell +--- + .../devicetree/bindings/pwm/pwm-rp1.yaml | 38 ++++ + drivers/pwm/Kconfig | 9 + + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-rp1.c | 203 ++++++++++++++++++ + 4 files changed, 251 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pwm/pwm-rp1.yaml + create mode 100644 drivers/pwm/pwm-rp1.c + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pwm/pwm-rp1.yaml +@@ -0,0 +1,38 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/pwm/pwm-rp1.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Raspberry Pi RP1 PWM controller ++ ++maintainers: ++ - Naushir Patuck ++ ++properties: ++ compatible: ++ enum: ++ - raspberrypi,rp1-pwm ++ ++ reg: ++ maxItems: 1 ++ ++ "#pwm-cells": ++ const: 3 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - "#pwm-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ pwm0: pwm@98000 { ++ compatible = "raspberrypi,rp1-pwm"; ++ reg = <0x0 0x98000 0x0 0x100>; ++ clocks = <&rp1_sys>; ++ #pwm-cells = <3>; ++ }; +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -451,6 +451,15 @@ config PWM_RASPBERRYPI_POE + Enable Raspberry Pi firmware controller PWM bus used to control the + official RPI PoE hat + ++config PWM_RP1 ++ tristate "RP1 PWM support" ++ depends on ARCH_BCM2835 || COMPILE_TEST ++ help ++ PWM framework driver for Raspberry Pi RP1 controller ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-rp1. ++ + config PWM_RCAR + tristate "Renesas R-Car PWM support" + depends on ARCH_RENESAS || COMPILE_TEST +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -41,6 +41,7 @@ obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-om + obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o + obj-$(CONFIG_PWM_PXA) += pwm-pxa.o + obj-$(CONFIG_PWM_RASPBERRYPI_POE) += pwm-raspberrypi-poe.o ++obj-$(CONFIG_PWM_RP1) += pwm-rp1.o + obj-$(CONFIG_PWM_RCAR) += pwm-rcar.o + obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o + obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o +--- /dev/null ++++ b/drivers/pwm/pwm-rp1.c +@@ -0,0 +1,203 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * pwm-rp1.c ++ * ++ * Raspberry Pi RP1 PWM. ++ * ++ * Copyright © 2023 Raspberry Pi Ltd. ++ * ++ * Author: Naushir Patuck (naush@raspberrypi.com) ++ * ++ * Based on the pwm-bcm2835 driver by: ++ * Bart Tanghe ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PWM_GLOBAL_CTRL 0x000 ++#define PWM_CHANNEL_CTRL(x) (0x014 + ((x) * 16)) ++#define PWM_RANGE(x) (0x018 + ((x) * 16)) ++#define PWM_DUTY(x) (0x020 + ((x) * 16)) ++ ++/* 8:FIFO_POP_MASK + 0:Trailing edge M/S modulation */ ++#define PWM_CHANNEL_DEFAULT (BIT(8) + BIT(0)) ++#define PWM_CHANNEL_ENABLE(x) BIT(x) ++#define PWM_POLARITY BIT(3) ++#define SET_UPDATE BIT(31) ++#define PWM_MODE_MASK GENMASK(1, 0) ++ ++struct rp1_pwm { ++ struct pwm_chip chip; ++ struct device *dev; ++ void __iomem *base; ++ struct clk *clk; ++}; ++ ++static inline struct rp1_pwm *to_rp1_pwm(struct pwm_chip *chip) ++{ ++ return container_of(chip, struct rp1_pwm, chip); ++} ++ ++static void rp1_pwm_apply_config(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct rp1_pwm *pc = to_rp1_pwm(chip); ++ u32 value; ++ ++ value = readl(pc->base + PWM_GLOBAL_CTRL); ++ value |= SET_UPDATE; ++ writel(value, pc->base + PWM_GLOBAL_CTRL); ++} ++ ++static int rp1_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct rp1_pwm *pc = to_rp1_pwm(chip); ++ ++ writel(PWM_CHANNEL_DEFAULT, pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm)); ++ return 0; ++} ++ ++static void rp1_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct rp1_pwm *pc = to_rp1_pwm(chip); ++ u32 value; ++ ++ value = readl(pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm)); ++ value &= ~PWM_MODE_MASK; ++ writel(value, pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm)); ++ rp1_pwm_apply_config(chip, pwm); ++} ++ ++static int rp1_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ++ const struct pwm_state *state) ++{ ++ struct rp1_pwm *pc = to_rp1_pwm(chip); ++ unsigned long clk_rate = clk_get_rate(pc->clk); ++ unsigned long clk_period; ++ u32 value; ++ ++ if (!clk_rate) { ++ dev_err(pc->dev, "failed to get clock rate\n"); ++ return -EINVAL; ++ } ++ ++ /* set period */ ++ clk_period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, clk_rate); ++ ++ writel(DIV_ROUND_CLOSEST(state->duty_cycle, clk_period), ++ pc->base + PWM_DUTY(pwm->hwpwm)); ++ ++ /* set duty cycle */ ++ writel(DIV_ROUND_CLOSEST(state->period, clk_period), ++ pc->base + PWM_RANGE(pwm->hwpwm)); ++ ++ /* set polarity */ ++ value = readl(pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm)); ++ if (state->polarity == PWM_POLARITY_NORMAL) ++ value &= ~PWM_POLARITY; ++ else ++ value |= PWM_POLARITY; ++ writel(value, pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm)); ++ ++ /* enable/disable */ ++ value = readl(pc->base + PWM_GLOBAL_CTRL); ++ if (state->enabled) ++ value |= PWM_CHANNEL_ENABLE(pwm->hwpwm); ++ else ++ value &= ~PWM_CHANNEL_ENABLE(pwm->hwpwm); ++ writel(value, pc->base + PWM_GLOBAL_CTRL); ++ ++ rp1_pwm_apply_config(chip, pwm); ++ ++ return 0; ++} ++ ++static const struct pwm_ops rp1_pwm_ops = { ++ .request = rp1_pwm_request, ++ .free = rp1_pwm_free, ++ .apply = rp1_pwm_apply, ++ .owner = THIS_MODULE, ++}; ++ ++static int rp1_pwm_probe(struct platform_device *pdev) ++{ ++ struct rp1_pwm *pc; ++ struct resource *res; ++ int ret; ++ ++ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ pc->dev = &pdev->dev; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ pc->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(pc->base)) ++ return PTR_ERR(pc->base); ++ ++ pc->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pc->clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), ++ "clock not found\n"); ++ ++ ret = clk_prepare_enable(pc->clk); ++ if (ret) ++ return ret; ++ ++ pc->chip.dev = &pdev->dev; ++ pc->chip.ops = &rp1_pwm_ops; ++ pc->chip.base = -1; ++ pc->chip.npwm = 4; ++ pc->chip.of_xlate = of_pwm_xlate_with_flags; ++ pc->chip.of_pwm_n_cells = 3; ++ ++ platform_set_drvdata(pdev, pc); ++ ++ ret = pwmchip_add(&pc->chip); ++ if (ret < 0) ++ goto add_fail; ++ ++ return 0; ++ ++add_fail: ++ clk_disable_unprepare(pc->clk); ++ return ret; ++} ++ ++static int rp1_pwm_remove(struct platform_device *pdev) ++{ ++ struct rp1_pwm *pc = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(pc->clk); ++ ++ pwmchip_remove(&pc->chip); ++ ++ return 0; ++} ++ ++static const struct of_device_id rp1_pwm_of_match[] = { ++ { .compatible = "raspberrypi,rp1-pwm" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rp1_pwm_of_match); ++ ++static struct platform_driver rp1_pwm_driver = { ++ .driver = { ++ .name = "rpi-pwm", ++ .of_match_table = rp1_pwm_of_match, ++ }, ++ .probe = rp1_pwm_probe, ++ .remove = rp1_pwm_remove, ++}; ++module_platform_driver(rp1_pwm_driver); ++ ++MODULE_AUTHOR("Naushir Patuck +Date: Tue, 14 Feb 2023 14:58:33 +0000 +Subject: [PATCH] drm: Add RP1 DSI driver + +Add support for the RP1 DSI hardware. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/Kconfig | 2 + + drivers/gpu/drm/Makefile | 1 + + drivers/gpu/drm/rp1/Kconfig | 5 + + drivers/gpu/drm/rp1/Makefile | 4 + + drivers/gpu/drm/rp1/rp1-dsi/Kconfig | 15 + + drivers/gpu/drm/rp1/rp1-dsi/Makefile | 5 + + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c | 537 ++++++++ + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h | 94 ++ + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dma.c | 443 ++++++ + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c | 1504 +++++++++++++++++++++ + 10 files changed, 2610 insertions(+) + create mode 100644 drivers/gpu/drm/rp1/Kconfig + create mode 100644 drivers/gpu/drm/rp1/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/Kconfig + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dma.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c + +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -384,6 +384,8 @@ source "drivers/gpu/drm/v3d/Kconfig" + + source "drivers/gpu/drm/vc4/Kconfig" + ++source "drivers/gpu/drm/rp1/Kconfig" ++ + source "drivers/gpu/drm/etnaviv/Kconfig" + + source "drivers/gpu/drm/hisilicon/Kconfig" +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -148,3 +148,4 @@ obj-y += gud/ + obj-$(CONFIG_DRM_HYPERV) += hyperv/ + obj-y += solomon/ + obj-$(CONFIG_DRM_SPRD) += sprd/ ++obj-y += rp1/ +--- /dev/null ++++ b/drivers/gpu/drm/rp1/Kconfig +@@ -0,0 +1,5 @@ ++source "drivers/gpu/drm/rp1/rp1-dsi/Kconfig" ++ ++source "drivers/gpu/drm/rp1/rp1-dpi/Kconfig" ++ ++source "drivers/gpu/drm/rp1/rp1-vec/Kconfig" +--- /dev/null ++++ b/drivers/gpu/drm/rp1/Makefile +@@ -0,0 +1,4 @@ ++obj-$(CONFIG_DRM_RP1_DSI) += rp1-dsi/ ++obj-$(CONFIG_DRM_RP1_DPI) += rp1-dpi/ ++obj-$(CONFIG_DRM_RP1_VEC) += rp1-vec/ ++ +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/Kconfig +@@ -0,0 +1,15 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config DRM_RP1_DSI ++ tristate "DRM Support for RP1 DSI" ++ depends on DRM ++ select MFD_RP1 ++ select DRM_GEM_DMA_HELPER ++ select DRM_KMS_HELPER ++ select DRM_MIPI_DSI ++ select DRM_VRAM_HELPER ++ select DRM_TTM ++ select DRM_TTM_HELPER ++ select GENERIC_PHY ++ select GENERIC_PHY_MIPI_DPHY ++ help ++ Choose this option to enable DSI display on RP1 +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++drm-rp1-dsi-y := rp1_dsi.o rp1_dsi_dma.o rp1_dsi_dsi.o ++ ++obj-$(CONFIG_DRM_RP1_DSI) += drm-rp1-dsi.o +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c +@@ -0,0 +1,537 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dsi.h" ++ ++static inline struct rp1_dsi * ++bridge_to_rp1_dsi(struct drm_bridge *bridge) ++{ ++ return container_of(bridge, struct rp1_dsi, bridge); ++} ++ ++static void rp1_dsi_bridge_pre_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++ struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge); ++ ++ rp1dsi_dsi_setup(dsi, &dsi->pipe.crtc.state->adjusted_mode); ++} ++ ++static void rp1_dsi_bridge_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++} ++ ++static void rp1_dsi_bridge_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *state) ++{ ++} ++ ++static void rp1_dsi_bridge_post_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *state) ++{ ++ struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge); ++ ++ if (dsi->dsi_running) { ++ rp1dsi_dsi_stop(dsi); ++ dsi->dsi_running = false; ++ } ++} ++ ++static int rp1_dsi_bridge_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge); ++ ++ /* Attach the panel or bridge to the dsi bridge */ ++ return drm_bridge_attach(bridge->encoder, dsi->out_bridge, ++ &dsi->bridge, flags); ++ return 0; ++} ++ ++static const struct drm_bridge_funcs rp1_dsi_bridge_funcs = { ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_reset = drm_atomic_helper_bridge_reset, ++ .atomic_pre_enable = rp1_dsi_bridge_pre_enable, ++ .atomic_enable = rp1_dsi_bridge_enable, ++ .atomic_disable = rp1_dsi_bridge_disable, ++ .atomic_post_disable = rp1_dsi_bridge_post_disable, ++ .attach = rp1_dsi_bridge_attach, ++}; ++ ++static void rp1dsi_pipe_update(struct drm_simple_display_pipe *pipe, ++ struct drm_plane_state *old_state) ++{ ++ struct drm_pending_vblank_event *event; ++ unsigned long flags; ++ struct drm_framebuffer *fb = pipe->plane.state->fb; ++ struct rp1_dsi *dsi = pipe->crtc.dev->dev_private; ++ struct drm_gem_object *gem = fb ? drm_gem_fb_get_obj(fb, 0) : NULL; ++ struct drm_gem_dma_object *dma_obj = gem ? to_drm_gem_dma_obj(gem) : NULL; ++ bool can_update = fb && dma_obj && dsi && dsi->pipe_enabled; ++ ++ /* (Re-)start DSI,DMA where required; and update FB address */ ++ if (can_update) { ++ if (!dsi->dma_running || fb->format->format != dsi->cur_fmt) { ++ if (dsi->dma_running && fb->format->format != dsi->cur_fmt) { ++ rp1dsi_dma_stop(dsi); ++ dsi->dma_running = false; ++ } ++ if (!dsi->dma_running) { ++ rp1dsi_dma_setup(dsi, ++ fb->format->format, dsi->display_format, ++ &pipe->crtc.state->adjusted_mode); ++ dsi->dma_running = true; ++ } ++ dsi->cur_fmt = fb->format->format; ++ drm_crtc_vblank_on(&pipe->crtc); ++ } ++ rp1dsi_dma_update(dsi, dma_obj->dma_addr, fb->offsets[0], fb->pitches[0]); ++ } ++ ++ /* Arm VBLANK event (or call it immediately in some error cases) */ ++ spin_lock_irqsave(&pipe->crtc.dev->event_lock, flags); ++ event = pipe->crtc.state->event; ++ if (event) { ++ pipe->crtc.state->event = NULL; ++ if (can_update && drm_crtc_vblank_get(&pipe->crtc) == 0) ++ drm_crtc_arm_vblank_event(&pipe->crtc, event); ++ else ++ drm_crtc_send_vblank_event(&pipe->crtc, event); ++ } ++ spin_unlock_irqrestore(&pipe->crtc.dev->event_lock, flags); ++} ++ ++static inline struct rp1_dsi * ++encoder_to_rp1_dsi(struct drm_encoder *encoder) ++{ ++ struct drm_simple_display_pipe *pipe = ++ container_of(encoder, struct drm_simple_display_pipe, encoder); ++ return container_of(pipe, struct rp1_dsi, pipe); ++} ++ ++static void rp1dsi_encoder_enable(struct drm_encoder *encoder) ++{ ++ struct rp1_dsi *dsi = encoder_to_rp1_dsi(encoder); ++ ++ /* Put DSI into video mode before starting video */ ++ rp1dsi_dsi_set_cmdmode(dsi, 0); ++ ++ /* Start DMA -> DPI */ ++ dsi->pipe_enabled = true; ++ dsi->cur_fmt = 0xdeadbeef; ++ rp1dsi_pipe_update(&dsi->pipe, 0); ++} ++ ++static void rp1dsi_encoder_disable(struct drm_encoder *encoder) ++{ ++ struct rp1_dsi *dsi = encoder_to_rp1_dsi(encoder); ++ ++ drm_crtc_vblank_off(&dsi->pipe.crtc); ++ if (dsi->dma_running) { ++ rp1dsi_dma_stop(dsi); ++ dsi->dma_running = false; ++ } ++ dsi->pipe_enabled = false; ++ ++ /* Return to command mode after stopping video */ ++ rp1dsi_dsi_set_cmdmode(dsi, 1); ++} ++ ++static const struct drm_encoder_helper_funcs rp1_dsi_encoder_funcs = { ++ .enable = rp1dsi_encoder_enable, ++ .disable = rp1dsi_encoder_disable, ++}; ++ ++static void rp1dsi_pipe_enable(struct drm_simple_display_pipe *pipe, ++ struct drm_crtc_state *crtc_state, ++ struct drm_plane_state *plane_state) ++{ ++} ++ ++static void rp1dsi_pipe_disable(struct drm_simple_display_pipe *pipe) ++{ ++} ++ ++static int rp1dsi_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dsi *dsi = pipe->crtc.dev->dev_private; ++ ++ if (dsi) ++ rp1dsi_dma_vblank_ctrl(dsi, 1); ++ ++ return 0; ++} ++ ++static void rp1dsi_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dsi *dsi = pipe->crtc.dev->dev_private; ++ ++ if (dsi) ++ rp1dsi_dma_vblank_ctrl(dsi, 0); ++} ++ ++static const struct drm_simple_display_pipe_funcs rp1dsi_pipe_funcs = { ++ .enable = rp1dsi_pipe_enable, ++ .update = rp1dsi_pipe_update, ++ .disable = rp1dsi_pipe_disable, ++ .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, ++ .enable_vblank = rp1dsi_pipe_enable_vblank, ++ .disable_vblank = rp1dsi_pipe_disable_vblank, ++}; ++ ++static const struct drm_mode_config_funcs rp1dsi_mode_funcs = { ++ .fb_create = drm_gem_fb_create, ++ .atomic_check = drm_atomic_helper_check, ++ .atomic_commit = drm_atomic_helper_commit, ++}; ++ ++static const u32 rp1dsi_formats[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565 ++}; ++ ++static void rp1dsi_stopall(struct drm_device *drm) ++{ ++ if (drm->dev_private) { ++ struct rp1_dsi *dsi = drm->dev_private; ++ ++ if (dsi->dma_running || rp1dsi_dma_busy(dsi)) { ++ rp1dsi_dma_stop(dsi); ++ dsi->dma_running = false; ++ } ++ if (dsi->dsi_running) { ++ rp1dsi_dsi_stop(dsi); ++ dsi->dsi_running = false; ++ } ++ if (dsi->clocks[RP1DSI_CLOCK_CFG]) ++ clk_disable_unprepare(dsi->clocks[RP1DSI_CLOCK_CFG]); ++ } ++} ++ ++DEFINE_DRM_GEM_DMA_FOPS(rp1dsi_fops); ++ ++static struct drm_driver rp1dsi_driver = { ++ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, ++ .fops = &rp1dsi_fops, ++ .name = "drm-rp1-dsi", ++ .desc = "drm-rp1-dsi", ++ .date = "0", ++ .major = 1, ++ .minor = 0, ++ DRM_GEM_DMA_DRIVER_OPS, ++ .release = rp1dsi_stopall, ++}; ++ ++static int rp1dsi_bind(struct rp1_dsi *dsi) ++{ ++ struct platform_device *pdev = dsi->pdev; ++ struct drm_device *drm = dsi->drm; ++ int ret; ++ ++ dsi->out_bridge = drmm_of_get_bridge(drm, pdev->dev.of_node, 0, 0); ++ if (IS_ERR(dsi->out_bridge)) ++ return PTR_ERR(dsi->out_bridge); ++ ++ ret = drmm_mode_config_init(drm); ++ if (ret) ++ goto rtn; ++ ++ drm->mode_config.max_width = 4096; ++ drm->mode_config.max_height = 4096; ++ drm->mode_config.fb_base = 0; ++ drm->mode_config.preferred_depth = 32; ++ drm->mode_config.prefer_shadow = 0; ++ drm->mode_config.prefer_shadow_fbdev = 1; ++ drm->mode_config.quirk_addfb_prefer_host_byte_order = true; ++ drm->mode_config.funcs = &rp1dsi_mode_funcs; ++ drm_vblank_init(drm, 1); ++ ++ ret = drm_simple_display_pipe_init(drm, ++ &dsi->pipe, ++ &rp1dsi_pipe_funcs, ++ rp1dsi_formats, ++ ARRAY_SIZE(rp1dsi_formats), ++ NULL, NULL); ++ if (ret) ++ goto rtn; ++ ++ /* We need slightly more complex encoder handling (enabling/disabling ++ * video mode), so add encoder helper functions. ++ */ ++ drm_encoder_helper_add(&dsi->pipe.encoder, &rp1_dsi_encoder_funcs); ++ ++ ret = drm_simple_display_pipe_attach_bridge(&dsi->pipe, &dsi->bridge); ++ if (ret) ++ goto rtn; ++ ++ drm_bridge_add(&dsi->bridge); ++ ++ drm_mode_config_reset(drm); ++ ++ if (dsi->clocks[RP1DSI_CLOCK_CFG]) ++ clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_CFG]); ++ ++ ret = drm_dev_register(drm, 0); ++ ++ if (ret == 0) ++ drm_fbdev_generic_setup(drm, 32); ++ ++rtn: ++ if (ret) ++ dev_err(&pdev->dev, "%s returned %d\n", __func__, ret); ++ else ++ dev_info(&pdev->dev, "%s succeeded", __func__); ++ ++ return ret; ++} ++ ++static void rp1dsi_unbind(struct rp1_dsi *dsi) ++{ ++ struct drm_device *drm = dsi->drm; ++ ++ rp1dsi_stopall(drm); ++ drm_dev_unregister(drm); ++ drm_atomic_helper_shutdown(drm); ++} ++ ++int rp1dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *dsi_dev) ++{ ++ struct rp1_dsi *dsi = container_of(host, struct rp1_dsi, dsi_host); ++ ++ dev_info(&dsi->pdev->dev, "%s: Attach DSI device name=%s channel=%d lanes=%d format=%d flags=0x%lx hs_rate=%lu lp_rate=%lu", ++ __func__, dsi_dev->name, dsi_dev->channel, dsi_dev->lanes, ++ dsi_dev->format, dsi_dev->mode_flags, dsi_dev->hs_rate, ++ dsi_dev->lp_rate); ++ dsi->vc = dsi_dev->channel & 3; ++ dsi->lanes = dsi_dev->lanes; ++ ++ switch (dsi_dev->format) { ++ case MIPI_DSI_FMT_RGB666: ++ case MIPI_DSI_FMT_RGB666_PACKED: ++ case MIPI_DSI_FMT_RGB565: ++ case MIPI_DSI_FMT_RGB888: ++ break; ++ default: ++ return -EINVAL; ++ } ++ dsi->display_format = dsi_dev->format; ++ dsi->display_flags = dsi_dev->mode_flags; ++ dsi->display_hs_rate = dsi_dev->hs_rate; ++ dsi->display_lp_rate = dsi_dev->lp_rate; ++ ++ /* ++ * Previously, we added a separate component to handle panel/bridge ++ * discovery and DRM registration, but now it's just a function call. ++ * The downstream/attaching device should deal with -EPROBE_DEFER ++ */ ++ return rp1dsi_bind(dsi); ++} ++ ++int rp1dsi_host_detach(struct mipi_dsi_host *host, struct mipi_dsi_device *dsi_dev) ++{ ++ struct rp1_dsi *dsi = container_of(host, struct rp1_dsi, dsi_host); ++ ++ /* ++ * Unregister the DRM driver. ++ * TODO: Check we are cleaning up correctly and not doing things multiple times! ++ */ ++ rp1dsi_unbind(dsi); ++ return 0; ++} ++ ++ssize_t rp1dsi_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) ++{ ++ struct rp1_dsi *dsi = container_of(host, struct rp1_dsi, dsi_host); ++ struct mipi_dsi_packet packet; ++ int ret = 0; ++ ++ /* Write */ ++ ret = mipi_dsi_create_packet(&packet, msg); ++ if (ret) { ++ dev_err(dsi->drm->dev, "RP1DSI: failed to create packet: %d\n", ret); ++ return ret; ++ } ++ ++ rp1dsi_dsi_send(dsi, *(u32 *)(&packet.header), packet.payload_length, packet.payload); ++ ++ /* Optional read back */ ++ if (msg->rx_len && msg->rx_buf) ++ ret = rp1dsi_dsi_recv(dsi, msg->rx_len, msg->rx_buf); ++ ++ return (ssize_t)ret; ++} ++ ++static const struct mipi_dsi_host_ops rp1dsi_mipi_dsi_host_ops = { ++ .attach = rp1dsi_host_attach, ++ .detach = rp1dsi_host_detach, ++ .transfer = rp1dsi_host_transfer ++}; ++ ++static int rp1dsi_platform_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct drm_device *drm; ++ struct rp1_dsi *dsi; ++ int i, ret; ++ ++ drm = drm_dev_alloc(&rp1dsi_driver, dev); ++ if (IS_ERR(drm)) { ++ ret = PTR_ERR(drm); ++ return ret; ++ } ++ dsi = drmm_kzalloc(drm, sizeof(*dsi), GFP_KERNEL); ++ if (!dsi) { ++ ret = -ENOMEM; ++ goto err_free_drm; ++ } ++ init_completion(&dsi->finished); ++ dsi->drm = drm; ++ dsi->pdev = pdev; ++ drm->dev_private = dsi; ++ platform_set_drvdata(pdev, drm); ++ ++ dsi->bridge.funcs = &rp1_dsi_bridge_funcs; ++ dsi->bridge.of_node = dev->of_node; ++ dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; ++ ++ /* Safe default values for DSI mode */ ++ dsi->lanes = 1; ++ dsi->display_format = MIPI_DSI_FMT_RGB888; ++ dsi->display_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; ++ ++ /* Hardware resources */ ++ for (i = 0; i < RP1DSI_NUM_CLOCKS; i++) { ++ static const char * const myclocknames[RP1DSI_NUM_CLOCKS] = { ++ "cfgclk", "dpiclk", "byteclk", "refclk" ++ }; ++ dsi->clocks[i] = devm_clk_get(dev, myclocknames[i]); ++ if (IS_ERR(dsi->clocks[i])) { ++ ret = PTR_ERR(dsi->clocks[i]); ++ dev_err(dev, "Error getting clocks[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ++ for (i = 0; i < RP1DSI_NUM_HW_BLOCKS; i++) { ++ dsi->hw_base[i] = ++ devm_ioremap_resource(dev, ++ platform_get_resource(dsi->pdev, ++ IORESOURCE_MEM, ++ i)); ++ if (IS_ERR(dsi->hw_base[i])) { ++ ret = PTR_ERR(dsi->hw_base[i]); ++ dev_err(dev, "Error memory mapping regs[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ret = platform_get_irq(dsi->pdev, 0); ++ if (ret > 0) ++ ret = devm_request_irq(dev, ret, rp1dsi_dma_isr, ++ IRQF_SHARED, "rp1-dsi", dsi); ++ if (ret) { ++ dev_err(dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_free_drm; ++ } ++ rp1dsi_mipicfg_setup(dsi); ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); ++ ++ /* Create the MIPI DSI Host and wait for the panel/bridge to attach to it */ ++ dsi->dsi_host.ops = &rp1dsi_mipi_dsi_host_ops; ++ dsi->dsi_host.dev = dev; ++ ret = mipi_dsi_host_register(&dsi->dsi_host); ++ if (ret) ++ goto err_free_drm; ++ ++ return ret; ++ ++err_free_drm: ++ dev_err(dev, "%s fail %d\n", __func__, ret); ++ drm_dev_put(drm); ++ return ret; ++} ++ ++static int rp1dsi_platform_remove(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ struct rp1_dsi *dsi = drm->dev_private; ++ ++ mipi_dsi_host_unregister(&dsi->dsi_host); ++ return 0; ++} ++ ++static void rp1dsi_platform_shutdown(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1dsi_stopall(drm); ++} ++ ++static const struct of_device_id rp1dsi_of_match[] = { ++ { ++ .compatible = "raspberrypi,rp1dsi", ++ }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rp1dsi_of_match); ++ ++static struct platform_driver rp1dsi_platform_driver = { ++ .probe = rp1dsi_platform_probe, ++ .remove = rp1dsi_platform_remove, ++ .shutdown = rp1dsi_platform_shutdown, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rp1dsi_of_match, ++ }, ++}; ++ ++module_platform_driver(rp1dsi_platform_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("MIPI DSI driver for Raspberry Pi RP1"); ++MODULE_AUTHOR("Nick Hollinghurst"); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h +@@ -0,0 +1,94 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++#ifndef _RP1_DSI_H_ ++#define _RP1_DSI_H_ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "drm-rp1-dsi" ++#define DRIVER_NAME "drm-rp1-dsi" ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define RP1DSI_HW_BLOCK_DMA 0 ++#define RP1DSI_HW_BLOCK_DSI 1 ++#define RP1DSI_HW_BLOCK_CFG 2 ++#define RP1DSI_NUM_HW_BLOCKS 3 ++ ++#define RP1DSI_CLOCK_CFG 0 ++#define RP1DSI_CLOCK_DPI 1 ++#define RP1DSI_CLOCK_BYTE 2 ++#define RP1DSI_CLOCK_REF 3 ++#define RP1DSI_NUM_CLOCKS 4 ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct rp1_dsi { ++ /* DRM and platform device pointers */ ++ struct drm_device *drm; ++ struct platform_device *pdev; ++ ++ /* Framework and helper objects */ ++ struct drm_simple_display_pipe pipe; ++ struct drm_bridge bridge; ++ struct drm_bridge *out_bridge; ++ struct mipi_dsi_host dsi_host; ++ ++ /* Clocks. We need DPI clock; the others are frequency references */ ++ struct clk *clocks[RP1DSI_NUM_CLOCKS]; ++ ++ /* Block (DSI DMA, DSI Host) base addresses, and current state */ ++ void __iomem *hw_base[RP1DSI_NUM_HW_BLOCKS]; ++ u32 cur_fmt; ++ bool dsi_running, dma_running, pipe_enabled; ++ struct completion finished; ++ ++ /* Attached display parameters (from mipi_dsi_device) */ ++ unsigned long display_flags, display_hs_rate, display_lp_rate; ++ enum mipi_dsi_pixel_format display_format; ++ u8 vc; ++ u8 lanes; ++ ++ /* DPHY */ ++ u8 hsfreq_index; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the DSI/DPI/DMA block */ ++ ++void rp1dsi_dma_setup(struct rp1_dsi *dsi, ++ u32 in_format, enum mipi_dsi_pixel_format out_format, ++ struct drm_display_mode const *mode); ++void rp1dsi_dma_update(struct rp1_dsi *dsi, dma_addr_t addr, u32 offset, u32 stride); ++void rp1dsi_dma_stop(struct rp1_dsi *dsi); ++int rp1dsi_dma_busy(struct rp1_dsi *dsi); ++irqreturn_t rp1dsi_dma_isr(int irq, void *dev); ++void rp1dsi_dma_vblank_ctrl(struct rp1_dsi *dsi, int enable); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the MIPICFG block and check RP1 platform */ ++ ++void rp1dsi_mipicfg_setup(struct rp1_dsi *dsi); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the SNPS D-PHY and DSI block setup */ ++ ++void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode); ++void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 header, int len, const u8 *buf); ++int rp1dsi_dsi_recv(struct rp1_dsi *dsi, int len, u8 *buf); ++void rp1dsi_dsi_set_cmdmode(struct rp1_dsi *dsi, int cmd_mode); ++void rp1dsi_dsi_stop(struct rp1_dsi *dsi); ++ ++#endif ++ +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dma.c +@@ -0,0 +1,443 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "rp1_dsi.h" ++ ++// --- DPI DMA REGISTERS (derived from Argon firmware, via RP1 drivers/mipi, with corrections) --- ++ ++// Control ++#define DPI_DMA_CONTROL 0x0 ++#define DPI_DMA_CONTROL_ARM_SHIFT 0 ++#define DPI_DMA_CONTROL_ARM_MASK BIT(DPI_DMA_CONTROL_ARM_SHIFT) ++#define DPI_DMA_CONTROL_ALIGN16_SHIFT 2 ++#define DPI_DMA_CONTROL_ALIGN16_MASK BIT(DPI_DMA_CONTROL_ALIGN16_SHIFT) ++#define DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT 1 ++#define DPI_DMA_CONTROL_AUTO_REPEAT_MASK BIT(DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT) ++#define DPI_DMA_CONTROL_HIGH_WATER_SHIFT 3 ++#define DPI_DMA_CONTROL_HIGH_WATER_MASK (0x1FF << DPI_DMA_CONTROL_HIGH_WATER_SHIFT) ++#define DPI_DMA_CONTROL_DEN_POL_SHIFT 12 ++#define DPI_DMA_CONTROL_DEN_POL_MASK BIT(DPI_DMA_CONTROL_DEN_POL_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_POL_SHIFT 13 ++#define DPI_DMA_CONTROL_HSYNC_POL_MASK BIT(DPI_DMA_CONTROL_HSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_POL_SHIFT 14 ++#define DPI_DMA_CONTROL_VSYNC_POL_MASK BIT(DPI_DMA_CONTROL_VSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_COLORM_SHIFT 15 ++#define DPI_DMA_CONTROL_COLORM_MASK BIT(DPI_DMA_CONTROL_COLORM_SHIFT) ++#define DPI_DMA_CONTROL_SHUTDN_SHIFT 16 ++#define DPI_DMA_CONTROL_SHUTDN_MASK BIT(DPI_DMA_CONTROL_SHUTDN_SHIFT) ++#define DPI_DMA_CONTROL_HBP_EN_SHIFT 17 ++#define DPI_DMA_CONTROL_HBP_EN_MASK BIT(DPI_DMA_CONTROL_HBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HFP_EN_SHIFT 18 ++#define DPI_DMA_CONTROL_HFP_EN_MASK BIT(DPI_DMA_CONTROL_HFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VBP_EN_SHIFT 19 ++#define DPI_DMA_CONTROL_VBP_EN_MASK BIT(DPI_DMA_CONTROL_VBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VFP_EN_SHIFT 20 ++#define DPI_DMA_CONTROL_VFP_EN_MASK BIT(DPI_DMA_CONTROL_VFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_EN_SHIFT 21 ++#define DPI_DMA_CONTROL_HSYNC_EN_MASK BIT(DPI_DMA_CONTROL_HSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_EN_SHIFT 22 ++#define DPI_DMA_CONTROL_VSYNC_EN_MASK BIT(DPI_DMA_CONTROL_VSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_IMMED_SHIFT 23 ++#define DPI_DMA_CONTROL_FORCE_IMMED_MASK BIT(DPI_DMA_CONTROL_FORCE_IMMED_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT 24 ++#define DPI_DMA_CONTROL_FORCE_DRAIN_MASK BIT(DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT 25 ++#define DPI_DMA_CONTROL_FORCE_EMPTY_MASK BIT(DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT) ++ ++// IRQ_ENABLES ++#define DPI_DMA_IRQ_EN 0x04 ++#define DPI_DMA_IRQ_EN_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_EN_DMA_READY_MASK BIT(DPI_DMA_IRQ_EN_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_EN_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_EN_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_EN_FRAME_START_MASK BIT(DPI_DMA_IRQ_EN_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_EN_TE_SHIFT 4 ++#define DPI_DMA_IRQ_EN_TE_MASK BIT(DPI_DMA_IRQ_EN_TE_SHIFT) ++#define DPI_DMA_IRQ_EN_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_EN_ERROR_MASK BIT(DPI_DMA_IRQ_EN_ERROR_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_EN_MATCH_MASK BIT(DPI_DMA_IRQ_EN_MATCH_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT 16 ++#define DPI_DMA_IRQ_EN_MATCH_LINE_MASK (0xFFF << DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT) ++ ++// IRQ_FLAGS ++#define DPI_DMA_IRQ_FLAGS 0x08 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_MASK BIT(DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_MASK BIT(DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_TE_SHIFT 4 ++#define DPI_DMA_IRQ_FLAGS_TE_MASK BIT(DPI_DMA_IRQ_FLAGS_TE_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_FLAGS_ERROR_MASK BIT(DPI_DMA_IRQ_FLAGS_ERROR_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_FLAGS_MATCH_MASK BIT(DPI_DMA_IRQ_FLAGS_MATCH_SHIFT) ++ ++// QOS ++#define DPI_DMA_QOS 0xC ++#define DPI_DMA_QOS_DQOS_SHIFT 0 ++#define DPI_DMA_QOS_DQOS_MASK (0xF << DPI_DMA_QOS_DQOS_SHIFT) ++#define DPI_DMA_QOS_ULEV_SHIFT 4 ++#define DPI_DMA_QOS_ULEV_MASK (0xF << DPI_DMA_QOS_ULEV_SHIFT) ++#define DPI_DMA_QOS_UQOS_SHIFT 8 ++#define DPI_DMA_QOS_UQOS_MASK (0xF << DPI_DMA_QOS_UQOS_SHIFT) ++#define DPI_DMA_QOS_LLEV_SHIFT 12 ++#define DPI_DMA_QOS_LLEV_MASK (0xF << DPI_DMA_QOS_LLEV_SHIFT) ++#define DPI_DMA_QOS_LQOS_SHIFT 16 ++#define DPI_DMA_QOS_LQOS_MASK (0xF << DPI_DMA_QOS_LQOS_SHIFT) ++ ++// Panics ++#define DPI_DMA_PANICS 0x38 ++#define DPI_DMA_PANICS_UPPER_COUNT_SHIFT 0 ++#define DPI_DMA_PANICS_UPPER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_UPPER_COUNT_SHIFT) ++#define DPI_DMA_PANICS_LOWER_COUNT_SHIFT 16 ++#define DPI_DMA_PANICS_LOWER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_LOWER_COUNT_SHIFT) ++ ++// DMA Address Lower: ++#define DPI_DMA_DMA_ADDR_L 0x10 ++ ++// DMA Address Upper: ++#define DPI_DMA_DMA_ADDR_H 0x40 ++ ++// DMA stride ++#define DPI_DMA_DMA_STRIDE 0x14 ++ ++// Visible Area ++#define DPI_DMA_VISIBLE_AREA 0x18 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT 0 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT) ++#define DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT 16 ++#define DPI_DMA_VISIBLE_AREA_COLSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT) ++ ++// Sync width ++#define DPI_DMA_SYNC_WIDTH 0x1C ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT 0 ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT) ++#define DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT 16 ++#define DPI_DMA_SYNC_WIDTH_COLSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT) ++ ++// Back porch ++#define DPI_DMA_BACK_PORCH 0x20 ++#define DPI_DMA_BACK_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_BACK_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_BACK_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_BACK_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_COLSM1_SHIFT) ++ ++// Front porch ++#define DPI_DMA_FRONT_PORCH 0x24 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_FRONT_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_FRONT_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_COLSM1_SHIFT) ++ ++// Input masks ++#define DPI_DMA_IMASK 0x2C ++#define DPI_DMA_IMASK_R_SHIFT 0 ++#define DPI_DMA_IMASK_R_MASK (0x3FF << DPI_DMA_IMASK_R_SHIFT) ++#define DPI_DMA_IMASK_G_SHIFT 10 ++#define DPI_DMA_IMASK_G_MASK (0x3FF << DPI_DMA_IMASK_G_SHIFT) ++#define DPI_DMA_IMASK_B_SHIFT 20 ++#define DPI_DMA_IMASK_B_MASK (0x3FF << DPI_DMA_IMASK_B_SHIFT) ++ ++// Output Masks ++#define DPI_DMA_OMASK 0x30 ++#define DPI_DMA_OMASK_R_SHIFT 0 ++#define DPI_DMA_OMASK_R_MASK (0x3FF << DPI_DMA_OMASK_R_SHIFT) ++#define DPI_DMA_OMASK_G_SHIFT 10 ++#define DPI_DMA_OMASK_G_MASK (0x3FF << DPI_DMA_OMASK_G_SHIFT) ++#define DPI_DMA_OMASK_B_SHIFT 20 ++#define DPI_DMA_OMASK_B_MASK (0x3FF << DPI_DMA_OMASK_B_SHIFT) ++ ++// Shifts ++#define DPI_DMA_SHIFT 0x28 ++#define DPI_DMA_SHIFT_IR_SHIFT 0 ++#define DPI_DMA_SHIFT_IR_MASK (0x1F << DPI_DMA_SHIFT_IR_SHIFT) ++#define DPI_DMA_SHIFT_IG_SHIFT 5 ++#define DPI_DMA_SHIFT_IG_MASK (0x1F << DPI_DMA_SHIFT_IG_SHIFT) ++#define DPI_DMA_SHIFT_IB_SHIFT 10 ++#define DPI_DMA_SHIFT_IB_MASK (0x1F << DPI_DMA_SHIFT_IB_SHIFT) ++#define DPI_DMA_SHIFT_OR_SHIFT 15 ++#define DPI_DMA_SHIFT_OR_MASK (0x1F << DPI_DMA_SHIFT_OR_SHIFT) ++#define DPI_DMA_SHIFT_OG_SHIFT 20 ++#define DPI_DMA_SHIFT_OG_MASK (0x1F << DPI_DMA_SHIFT_OG_SHIFT) ++#define DPI_DMA_SHIFT_OB_SHIFT 25 ++#define DPI_DMA_SHIFT_OB_MASK (0x1F << DPI_DMA_SHIFT_OB_SHIFT) ++ ++// Scaling ++#define DPI_DMA_RGBSZ 0x34 ++#define DPI_DMA_RGBSZ_BPP_SHIFT 16 ++#define DPI_DMA_RGBSZ_BPP_MASK (0x3 << DPI_DMA_RGBSZ_BPP_SHIFT) ++#define DPI_DMA_RGBSZ_R_SHIFT 0 ++#define DPI_DMA_RGBSZ_R_MASK (0xF << DPI_DMA_RGBSZ_R_SHIFT) ++#define DPI_DMA_RGBSZ_G_SHIFT 4 ++#define DPI_DMA_RGBSZ_G_MASK (0xF << DPI_DMA_RGBSZ_G_SHIFT) ++#define DPI_DMA_RGBSZ_B_SHIFT 8 ++#define DPI_DMA_RGBSZ_B_MASK (0xF << DPI_DMA_RGBSZ_B_SHIFT) ++ ++// Status ++#define DPI_DMA_STATUS 0x3c ++ ++#define BITS(field, val) (((val) << (field ## _SHIFT)) & (field ## _MASK)) ++ ++static unsigned int rp1dsi_dma_read(struct rp1_dsi *dsi, unsigned int reg) ++{ ++ void __iomem *addr = dsi->hw_base[RP1DSI_HW_BLOCK_DMA] + reg; ++ ++ return readl(addr); ++} ++ ++static void rp1dsi_dma_write(struct rp1_dsi *dsi, unsigned int reg, unsigned int val) ++{ ++ void __iomem *addr = dsi->hw_base[RP1DSI_HW_BLOCK_DMA] + reg; ++ ++ writel(val, addr); ++} ++ ++int rp1dsi_dma_busy(struct rp1_dsi *dsi) ++{ ++ return (rp1dsi_dma_read(dsi, DPI_DMA_STATUS) & 0xF8F) ? 1 : 0; ++} ++ ++/* Table of supported input (in-memory/DMA) pixel formats. */ ++struct rp1dsi_ipixfmt { ++ u32 format; /* DRM format code */ ++ u32 mask; /* RGB masks (10 bits each, left justified) */ ++ u32 shift; /* RGB MSB positions in the memory word */ ++ u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */ ++}; ++ ++#define IMASK_RGB(r, g, b) (BITS(DPI_DMA_IMASK_R, r) | \ ++ BITS(DPI_DMA_IMASK_G, g) | \ ++ BITS(DPI_DMA_IMASK_B, b)) ++#define ISHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_IR, r) | \ ++ BITS(DPI_DMA_SHIFT_IG, g) | \ ++ BITS(DPI_DMA_SHIFT_IB, b)) ++ ++static const struct rp1dsi_ipixfmt my_formats[] = { ++ { ++ .format = DRM_FORMAT_XRGB8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_XBGR8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_RGB888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_BGR888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_RGB565, ++ .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = ISHIFT_RGB(15, 10, 4), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) | ++ BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1), ++ } ++}; ++ ++/* Choose the internal on-the-bus DPI format as expected by DSI Host. */ ++static u32 get_omask_oshift(enum mipi_dsi_pixel_format fmt, u32 *oshift) ++{ ++ switch (fmt) { ++ case MIPI_DSI_FMT_RGB565: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 15) | ++ BITS(DPI_DMA_SHIFT_OG, 10) | ++ BITS(DPI_DMA_SHIFT_OB, 4); ++ return BITS(DPI_DMA_OMASK_R, 0x3e0) | ++ BITS(DPI_DMA_OMASK_G, 0x3f0) | ++ BITS(DPI_DMA_OMASK_B, 0x3e0); ++ case MIPI_DSI_FMT_RGB666_PACKED: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 17) | ++ BITS(DPI_DMA_SHIFT_OG, 11) | ++ BITS(DPI_DMA_SHIFT_OB, 5); ++ return BITS(DPI_DMA_OMASK_R, 0x3f0) | ++ BITS(DPI_DMA_OMASK_G, 0x3f0) | ++ BITS(DPI_DMA_OMASK_B, 0x3f0); ++ case MIPI_DSI_FMT_RGB666: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 21) | ++ BITS(DPI_DMA_SHIFT_OG, 13) | ++ BITS(DPI_DMA_SHIFT_OB, 5); ++ return BITS(DPI_DMA_OMASK_R, 0x3f0) | ++ BITS(DPI_DMA_OMASK_G, 0x3f0) | ++ BITS(DPI_DMA_OMASK_B, 0x3f0); ++ default: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 23) | ++ BITS(DPI_DMA_SHIFT_OG, 15) | ++ BITS(DPI_DMA_SHIFT_OB, 7); ++ return BITS(DPI_DMA_OMASK_R, 0x3fc) | ++ BITS(DPI_DMA_OMASK_G, 0x3fc) | ++ BITS(DPI_DMA_OMASK_B, 0x3fc); ++ } ++} ++ ++void rp1dsi_dma_setup(struct rp1_dsi *dsi, ++ u32 in_format, enum mipi_dsi_pixel_format out_format, ++ struct drm_display_mode const *mode) ++{ ++ u32 oshift; ++ int i; ++ ++ /* ++ * Configure all DSI/DPI/DMA block registers, except base address. ++ * DMA will not actually start until a FB base address is specified ++ * using rp1dsi_dma_update(). ++ */ ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_VISIBLE_AREA, ++ BITS(DPI_DMA_VISIBLE_AREA_ROWSM1, mode->vdisplay - 1) | ++ BITS(DPI_DMA_VISIBLE_AREA_COLSM1, mode->hdisplay - 1)); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_SYNC_WIDTH, ++ BITS(DPI_DMA_SYNC_WIDTH_ROWSM1, mode->vsync_end - mode->vsync_start - 1) | ++ BITS(DPI_DMA_SYNC_WIDTH_COLSM1, mode->hsync_end - mode->hsync_start - 1)); ++ ++ /* In the DPIDMA registers, "back porch" time includes sync width */ ++ rp1dsi_dma_write(dsi, DPI_DMA_BACK_PORCH, ++ BITS(DPI_DMA_BACK_PORCH_ROWSM1, mode->vtotal - mode->vsync_start - 1) | ++ BITS(DPI_DMA_BACK_PORCH_COLSM1, mode->htotal - mode->hsync_start - 1)); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_FRONT_PORCH, ++ BITS(DPI_DMA_FRONT_PORCH_ROWSM1, mode->vsync_start - mode->vdisplay - 1) | ++ BITS(DPI_DMA_FRONT_PORCH_COLSM1, mode->hsync_start - mode->hdisplay - 1)); ++ ++ /* Input to output pixel format conversion */ ++ for (i = 0; i < ARRAY_SIZE(my_formats); ++i) { ++ if (my_formats[i].format == in_format) ++ break; ++ } ++ if (i >= ARRAY_SIZE(my_formats)) { ++ drm_err(dsi->drm, "%s: bad input format\n", __func__); ++ i = 0; ++ } ++ rp1dsi_dma_write(dsi, DPI_DMA_IMASK, my_formats[i].mask); ++ rp1dsi_dma_write(dsi, DPI_DMA_OMASK, get_omask_oshift(out_format, &oshift)); ++ rp1dsi_dma_write(dsi, DPI_DMA_SHIFT, my_formats[i].shift | oshift); ++ if (out_format == MIPI_DSI_FMT_RGB888) ++ rp1dsi_dma_write(dsi, DPI_DMA_RGBSZ, my_formats[i].rgbsz); ++ else ++ rp1dsi_dma_write(dsi, DPI_DMA_RGBSZ, my_formats[i].rgbsz & DPI_DMA_RGBSZ_BPP_MASK); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_QOS, ++ BITS(DPI_DMA_QOS_DQOS, 0x0) | ++ BITS(DPI_DMA_QOS_ULEV, 0xb) | ++ BITS(DPI_DMA_QOS_UQOS, 0x2) | ++ BITS(DPI_DMA_QOS_LLEV, 0x8) | ++ BITS(DPI_DMA_QOS_LQOS, 0x7)); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_FLAGS, -1); ++ rp1dsi_dma_vblank_ctrl(dsi, 1); ++ ++ i = rp1dsi_dma_busy(dsi); ++ if (i) ++ drm_err(dsi->drm, "RP1DSI: Unexpectedly busy at start!"); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_CONTROL, ++ BITS(DPI_DMA_CONTROL_ARM, (i == 0)) | ++ BITS(DPI_DMA_CONTROL_AUTO_REPEAT, 1) | ++ BITS(DPI_DMA_CONTROL_HIGH_WATER, 448) | ++ BITS(DPI_DMA_CONTROL_DEN_POL, 0) | ++ BITS(DPI_DMA_CONTROL_HSYNC_POL, 0) | ++ BITS(DPI_DMA_CONTROL_VSYNC_POL, 0) | ++ BITS(DPI_DMA_CONTROL_COLORM, 0) | ++ BITS(DPI_DMA_CONTROL_SHUTDN, 0) | ++ BITS(DPI_DMA_CONTROL_HBP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_HFP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_VBP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_VFP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_HSYNC_EN, 1) | ++ BITS(DPI_DMA_CONTROL_VSYNC_EN, 1)); ++} ++ ++void rp1dsi_dma_update(struct rp1_dsi *dsi, dma_addr_t addr, u32 offset, u32 stride) ++{ ++ /* ++ * Update STRIDE, DMAH and DMAL only. When called after rp1dsi_dma_setup(), ++ * DMA starts immediately; if already running, the buffer will flip at ++ * the next vertical sync event. ++ */ ++ u64 a = addr + offset; ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_DMA_STRIDE, stride); ++ rp1dsi_dma_write(dsi, DPI_DMA_DMA_ADDR_H, a >> 32); ++ rp1dsi_dma_write(dsi, DPI_DMA_DMA_ADDR_L, a & 0xFFFFFFFFu); ++} ++ ++void rp1dsi_dma_stop(struct rp1_dsi *dsi) ++{ ++ /* ++ * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for ++ * the current and any queued frame to end. "Force drain" flags are not used, ++ * as they seem to prevent DMA from re-starting properly; it's safer to wait. ++ */ ++ u32 ctrl; ++ ++ reinit_completion(&dsi->finished); ++ ctrl = rp1dsi_dma_read(dsi, DPI_DMA_CONTROL); ++ ctrl &= ~(DPI_DMA_CONTROL_ARM_MASK | DPI_DMA_CONTROL_AUTO_REPEAT_MASK); ++ rp1dsi_dma_write(dsi, DPI_DMA_CONTROL, ctrl); ++ if (!wait_for_completion_timeout(&dsi->finished, HZ / 10)) ++ drm_err(dsi->drm, "%s: timed out waiting for idle\n", __func__); ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_EN, 0); ++} ++ ++void rp1dsi_dma_vblank_ctrl(struct rp1_dsi *dsi, int enable) ++{ ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_EN, ++ BITS(DPI_DMA_IRQ_EN_AFIFO_EMPTY, 1) | ++ BITS(DPI_DMA_IRQ_EN_UNDERFLOW, 1) | ++ BITS(DPI_DMA_IRQ_EN_DMA_READY, !!enable) | ++ BITS(DPI_DMA_IRQ_EN_MATCH_LINE, 4095)); ++} ++ ++irqreturn_t rp1dsi_dma_isr(int irq, void *dev) ++{ ++ struct rp1_dsi *dsi = dev; ++ u32 u = rp1dsi_dma_read(dsi, DPI_DMA_IRQ_FLAGS); ++ ++ if (u) { ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_FLAGS, u); ++ if (dsi) { ++ if (u & DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK) ++ drm_err_ratelimited(dsi->drm, ++ "Underflow! (panics=0x%08x)\n", ++ rp1dsi_dma_read(dsi, DPI_DMA_PANICS)); ++ if (u & DPI_DMA_IRQ_FLAGS_DMA_READY_MASK) ++ drm_crtc_handle_vblank(&dsi->pipe.crtc); ++ if (u & DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK) ++ complete(&dsi->finished); ++ } ++ } ++ return u ? IRQ_HANDLED : IRQ_NONE; ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c +@@ -0,0 +1,1504 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "drm/drm_print.h" ++ ++#include "rp1_dsi.h" ++ ++/* ------------------------------- Synopsis DSI ------------------------ */ ++#define DSI_VERSION_CFG 0x000 ++#define DSI_PWR_UP 0x004 ++#define DSI_CLKMGR_CFG 0x008 ++#define DSI_DPI_VCID 0x00C ++#define DSI_DPI_COLOR_CODING 0x010 ++#define DSI_DPI_CFG_POL 0x014 ++#define DSI_DPI_LP_CMD_TIM 0x018 ++#define DSI_DBI_VCID 0x01C ++#define DSI_DBI_CFG 0x020 ++#define DSI_DBI_PARTITIONING_EN 0x024 ++#define DSI_DBI_CMDSIZE 0x028 ++#define DSI_PCKHDL_CFG 0x02C ++#define DSI_GEN_VCID 0x030 ++#define DSI_MODE_CFG 0x034 ++#define DSI_VID_MODE_CFG 0x038 ++#define DSI_VID_PKT_SIZE 0x03C ++#define DSI_VID_NUM_CHUNKS 0x040 ++#define DSI_VID_NULL_SIZE 0x044 ++#define DSI_VID_HSA_TIME 0x048 ++#define DSI_VID_HBP_TIME 0x04C ++#define DSI_VID_HLINE_TIME 0x050 ++#define DSI_VID_VSA_LINES 0x054 ++#define DSI_VID_VBP_LINES 0x058 ++#define DSI_VID_VFP_LINES 0x05C ++#define DSI_VID_VACTIVE_LINES 0x060 ++#define DSI_EDPI_CMD_SIZE 0x064 ++#define DSI_CMD_MODE_CFG 0x068 ++#define DSI_GEN_HDR 0x06C ++#define DSI_GEN_PLD_DATA 0x070 ++#define DSI_CMD_PKT_STATUS 0x074 ++#define DSI_TO_CNT_CFG 0x078 ++#define DSI_HS_RD_TO_CNT 0x07C ++#define DSI_LP_RD_TO_CNT 0x080 ++#define DSI_HS_WR_TO_CNT 0x084 ++#define DSI_LP_WR_TO_CNT 0x088 ++#define DSI_BTA_TO_CNT 0x08C ++#define DSI_SDF_3D 0x090 ++#define DSI_LPCLK_CTRL 0x094 ++#define DSI_PHY_TMR_LPCLK_CFG 0x098 ++#define DSI_PHY_TMR_HS2LP_LSB 16 ++#define DSI_PHY_TMR_LP2HS_LSB 0 ++#define DSI_PHY_TMR_CFG 0x09C ++#define DSI_PHY_TMR_RD_CFG 0x0F4 ++#define DSI_PHYRSTZ 0x0A0 ++#define DSI_PHY_IF_CFG 0x0A4 ++#define DSI_PHY_ULPS_CTRL 0x0A8 ++#define DSI_PHY_TX_TRIGGERS 0x0AC ++#define DSI_PHY_STATUS 0x0B0 ++ ++#define DSI_PHY_TST_CTRL0 0x0B4 ++#define DSI_PHY_TST_CTRL1 0x0B8 ++#define DSI_INT_ST0 0x0BC ++#define DSI_INT_ST1 0x0C0 ++#define DSI_INT_MASK0_CFG 0x0C4 ++#define DSI_INT_MASK1_CFG 0x0C8 ++#define DSI_PHY_CAL 0x0CC ++#define DSI_HEXP_NPKT_CLR 0x104 ++#define DSI_HEXP_NPKT_SIZE 0x108 ++#define DSI_VID_SHADOW_CTRL 0x100 ++ ++#define DSI_DPI_VCID_ACT 0x10C ++#define DSI_DPI_COLOR_CODING_ACT 0x110 ++#define DSI_DPI_LP_CMD_TIM_ACT 0x118 ++#define DSI_VID_MODE_CFG_ACT 0x138 ++#define DSI_VID_PKT_SIZE_ACT 0x13C ++#define DSI_VID_NUM_CHUNKS_ACT 0x140 ++#define DSI_VID_NULL_SIZE_ACT 0x144 ++#define DSI_VID_HSA_TIME_ACT 0x148 ++#define DSI_VID_HBP_TIME_ACT 0x14C ++#define DSI_VID_HLINE_TIME_ACT 0x150 ++#define DSI_VID_VSA_LINES_ACT 0x154 ++#define DSI_VID_VBP_LINES_ACT 0x158 ++#define DSI_VID_VFP_LINES_ACT 0x15C ++#define DSI_VID_VACTIVE_LINES_ACT 0x160 ++#define DSI_SDF_3D_CFG_ACT 0x190 ++ ++#define DSI_INT_FORCE0 0x0D8 ++#define DSI_INT_FORCE1 0x0DC ++ ++#define DSI_AUTO_ULPS_MODE 0x0E0 ++#define DSI_AUTO_ULPS_ENTRY_DELAY 0x0E4 ++#define DSI_AUTO_ULPS_WAKEUP_TIME 0x0E8 ++#define DSI_EDPI_ADV_FEATURES 0x0EC ++ ++#define DSI_DSC_PARAMETER 0x0F0 ++ ++/* And some bitfield definitions */ ++ ++#define DPHY_PWR_UP_SHUTDOWNZ_LSB 0 ++#define DPHY_PWR_UP_SHUTDOWNZ_BITS BIT(DPHY_PWR_UP_SHUTDOWNZ_LSB) ++ ++#define DPHY_CTRL0_PHY_TESTCLK_LSB 1 ++#define DPHY_CTRL0_PHY_TESTCLK_BITS BIT(DPHY_CTRL0_PHY_TESTCLK_LSB) ++#define DPHY_CTRL0_PHY_TESTCLR_LSB 0 ++#define DPHY_CTRL0_PHY_TESTCLR_BITS BIT(DPHY_CTRL0_PHY_TESTCLR_LSB) ++ ++#define DPHY_CTRL1_PHY_TESTDIN_LSB 0 ++#define DPHY_CTRL1_PHY_TESTDIN_BITS (0xff << DPHY_CTRL1_PHY_TESTDIN_LSB) ++#define DPHY_CTRL1_PHY_TESTDOUT_LSB 8 ++#define DPHY_CTRL1_PHY_TESTDOUT_BITS (0xff << DPHY_CTRL1_PHY_TESTDOUT_LSB) ++#define DPHY_CTRL1_PHY_TESTEN_LSB 16 ++#define DPHY_CTRL1_PHY_TESTEN_BITS BIT(DPHY_CTRL1_PHY_TESTEN_LSB) ++ ++#define DSI_PHYRSTZ_SHUTDOWNZ_LSB 0 ++#define DSI_PHYRSTZ_SHUTDOWNZ_BITS BIT(DSI_PHYRSTZ_SHUTDOWNZ_LSB) ++#define DSI_PHYRSTZ_RSTZ_LSB 1 ++#define DSI_PHYRSTZ_RSTZ_BITS BIT(DSI_PHYRSTZ_RSTZ_LSB) ++#define DSI_PHYRSTZ_ENABLECLK_LSB 2 ++#define DSI_PHYRSTZ_ENABLECLK_BITS BIT(DSI_PHYRSTZ_ENABLECLK_LSB) ++#define DSI_PHYRSTZ_FORCEPLL_LSB 3 ++#define DSI_PHYRSTZ_FORCEPLL_BITS BIT(DSI_PHYRSTZ_FORCEPLL_LSB) ++ ++#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44 ++#define DPHY_PLL_INPUT_DIV_OFFSET 0x17 ++#define DPHY_PLL_LOOP_DIV_OFFSET 0x18 ++#define DPHY_PLL_DIV_CTRL_OFFSET 0x19 ++ ++#define DPHY_PLL_BIAS_OFFSET 0x10 ++#define DPHY_PLL_BIAS_VCO_RANGE_LSB 3 ++#define DPHY_PLL_BIAS_USE_PROGRAMMED_VCO_RANGE BIT(7) ++ ++#define DPHY_PLL_CHARGE_PUMP_OFFSET 0x11 ++#define DPHY_PLL_LPF_OFFSET 0x12 ++ ++#define DSI_WRITE(reg, val) writel((val), dsi->hw_base[RP1DSI_HW_BLOCK_DSI] + (reg)) ++#define DSI_READ(reg) readl(dsi->hw_base[RP1DSI_HW_BLOCK_DSI] + (reg)) ++ ++// ================================================================================ ++// Register block : RPI_MIPICFG ++// Version : 1 ++// Bus type : apb ++// Description : Register block to control mipi DPHY ++// ================================================================================ ++#define RPI_MIPICFG_REGS_RWTYPE_MSB 13 ++#define RPI_MIPICFG_REGS_RWTYPE_LSB 12 ++// ================================================================================ ++// Register : RPI_MIPICFG_CLK2FC ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_CLK2FC_OFFSET 0x00000000 ++#define RPI_MIPICFG_CLK2FC_BITS 0x00000007 ++#define RPI_MIPICFG_CLK2FC_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CLK2FC_SEL ++// Description : select a clock to be sent to the frequency counter ++// 7 = none ++// 6 = none ++// 5 = none ++// 4 = rxbyteclkhs (187.5MHz) ++// 3 = rxclkesc0 (20MHz) ++// 2 = txbyteclkhs (187.5MHz) ++// 1 = txclkesc (125MHz) ++// 0 = none ++#define RPI_MIPICFG_CLK2FC_SEL_RESET 0x0 ++#define RPI_MIPICFG_CLK2FC_SEL_BITS 0x00000007 ++#define RPI_MIPICFG_CLK2FC_SEL_MSB 2 ++#define RPI_MIPICFG_CLK2FC_SEL_LSB 0 ++#define RPI_MIPICFG_CLK2FC_SEL_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_CFG ++// JTAG access : asynchronous ++// Description : Top level configuration ++#define RPI_MIPICFG_CFG_OFFSET 0x00000004 ++#define RPI_MIPICFG_CFG_BITS 0x00000111 ++#define RPI_MIPICFG_CFG_RESET 0x00000001 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CFG_DPIUPDATE ++// Description : Indicate the DSI block that the next frame will have a new video configuration ++#define RPI_MIPICFG_CFG_DPIUPDATE_RESET 0x0 ++#define RPI_MIPICFG_CFG_DPIUPDATE_BITS 0x00000100 ++#define RPI_MIPICFG_CFG_DPIUPDATE_MSB 8 ++#define RPI_MIPICFG_CFG_DPIUPDATE_LSB 8 ++#define RPI_MIPICFG_CFG_DPIUPDATE_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CFG_SEL_TE_EXT ++// Description : Select the TE source: 1 - ext, 0 - int ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_RESET 0x0 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_BITS 0x00000010 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_MSB 4 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_LSB 4 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CFG_SEL_CSI_DSI_N ++// Description : Select PHY direction: input to CSI, output from DSI. CSI 1 DSI 0 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_RESET 0x1 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_BITS 0x00000001 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_MSB 0 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_LSB 0 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_TE ++// JTAG access : synchronous ++// Description : Tearing effect processing ++#define RPI_MIPICFG_TE_OFFSET 0x00000008 ++#define RPI_MIPICFG_TE_BITS 0x10ffffff ++#define RPI_MIPICFG_TE_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_TE_ARM ++// Description : Tearing effect arm ++#define RPI_MIPICFG_TE_ARM_RESET 0x0 ++#define RPI_MIPICFG_TE_ARM_BITS 0x10000000 ++#define RPI_MIPICFG_TE_ARM_MSB 28 ++#define RPI_MIPICFG_TE_ARM_LSB 28 ++#define RPI_MIPICFG_TE_ARM_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_TE_HALT_CYC ++// Description : When arm pulse has been seen, wait for te; then halt the dpi block ++// for this many clk_dpi cycles ++#define RPI_MIPICFG_TE_HALT_CYC_RESET 0x000000 ++#define RPI_MIPICFG_TE_HALT_CYC_BITS 0x00ffffff ++#define RPI_MIPICFG_TE_HALT_CYC_MSB 23 ++#define RPI_MIPICFG_TE_HALT_CYC_LSB 0 ++#define RPI_MIPICFG_TE_HALT_CYC_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_MONITOR ++// JTAG access : asynchronous ++// Description : DPHY status monitors for analog DFT ++#define RPI_MIPICFG_DPHY_MONITOR_OFFSET 0x00000010 ++#define RPI_MIPICFG_DPHY_MONITOR_BITS 0x00111fff ++#define RPI_MIPICFG_DPHY_MONITOR_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_LOCK ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_BITS 0x00100000 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_MSB 20 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_LSB 20 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_BISTOK ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_BITS 0x00010000 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_MSB 16 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_LSB 16 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_BITS 0x00001000 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_MSB 12 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_LSB 12 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_BITS 0x00000f00 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_MSB 11 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_LSB 8 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_TESTDOUT ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_RESET 0x00 ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_MSB 7 ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_LSB 0 ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_0 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_0_OFFSET 0x00000014 ++#define RPI_MIPICFG_DPHY_CTRL_0_BITS 0x0000003f ++#define RPI_MIPICFG_DPHY_CTRL_0_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE ++// Description : When set in lpmode, TXCLKESC is driven from clk_vec(driven from clocks block) ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_BITS 0x00000020 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_MSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_LSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA ++// Description : When set, drive the DPHY from the test registers ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_BITS 0x00000010 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_MSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_LSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS ++// Description : When test_ena is set, disable cfg_clk ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_BITS 0x00000008 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_MSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_LSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS ++// Description : When test_ena is set, disable refclk ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_BITS 0x00000004 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_MSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_LSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS ++// Description : When test_ena is set, disable txclkesc ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_BITS 0x00000002 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_MSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_LSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS ++// Description : When test_ena is set, disable txbyteclkhs ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_BITS 0x00000001 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_MSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_1 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_1_OFFSET 0x00000018 ++#define RPI_MIPICFG_DPHY_CTRL_1_BITS 0x7fffffff ++#define RPI_MIPICFG_DPHY_CTRL_1_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_BITS 0x40000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_MSB 30 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_LSB 30 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_BITS 0x20000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_MSB 29 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_LSB 29 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_RSTZ ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_BITS 0x10000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_MSB 28 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_LSB 28 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_BITS 0x08000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_MSB 27 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_LSB 27 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BISTON ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_BITS 0x04000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_MSB 26 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_LSB 26 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_BITS 0x02000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_MSB 25 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_LSB 25 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_BITS 0x01000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_MSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_LSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_BITS 0x00800000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_MSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_LSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_BITS 0x00400000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_MSB 22 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_LSB 22 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_BITS 0x00200000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_MSB 21 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_LSB 21 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_BITS 0x00100000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_MSB 20 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_LSB 20 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_BITS 0x00080000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_MSB 19 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_LSB 19 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_BITS 0x00040000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_MSB 18 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_LSB 18 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_BITS 0x00020000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_MSB 17 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_LSB 17 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_BITS 0x00010000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_MSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_LSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_BITS 0x00008000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_MSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_LSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_BITS 0x00004000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_MSB 14 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_LSB 14 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_BITS 0x00002000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_MSB 13 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_LSB 13 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_BITS 0x00001000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_MSB 12 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_LSB 12 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_BITS 0x00000800 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_MSB 11 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_LSB 11 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_BITS 0x00000400 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_MSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_LSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_BITS 0x00000200 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_MSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_LSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_BITS 0x00000100 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_MSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_BITS 0x00000080 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_LSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_BITS 0x00000040 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_MSB 6 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_LSB 6 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_BITS 0x00000020 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_MSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_LSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_BITS 0x00000010 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_MSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_LSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_BITS 0x00000008 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_MSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_LSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_BITS 0x00000004 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_MSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_LSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_BITS 0x00000002 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_MSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_LSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_BITS 0x00000001 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_MSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_2 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_2_OFFSET 0x0000001c ++#define RPI_MIPICFG_DPHY_CTRL_2_BITS 0x000007ff ++#define RPI_MIPICFG_DPHY_CTRL_2_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTCLK ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_BITS 0x00000400 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_MSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_LSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTEN ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_BITS 0x00000200 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_MSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_LSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTCLR ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_BITS 0x00000100 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_MSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTDIN ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_3 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_3_OFFSET 0x00000020 ++#define RPI_MIPICFG_DPHY_CTRL_3_BITS 0xffffffff ++#define RPI_MIPICFG_DPHY_CTRL_3_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_BITS 0xff000000 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_MSB 31 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_LSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_BITS 0x00ff0000 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_MSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_LSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_BITS 0x0000ff00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_MSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_4 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_4_OFFSET 0x00000024 ++#define RPI_MIPICFG_DPHY_CTRL_4_BITS 0xffffffff ++#define RPI_MIPICFG_DPHY_CTRL_4_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_BITS 0xff000000 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_MSB 31 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_LSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_BITS 0x00ff0000 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_MSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_LSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_BITS 0x0000ff00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_MSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTR ++// JTAG access : synchronous ++// Description : Raw Interrupts ++#define RPI_MIPICFG_INTR_OFFSET 0x00000028 ++#define RPI_MIPICFG_INTR_BITS 0x0000000f ++#define RPI_MIPICFG_INTR_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTR_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTR_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTR_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTR_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTR_DSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTR_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTR_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTR_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTR_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTR_CSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTR_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTR_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTR_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTR_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTR_DSI_DMA_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTR_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTR_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTR_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTR_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTR_CSI_DMA_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTE ++// JTAG access : synchronous ++// Description : Interrupt Enable ++#define RPI_MIPICFG_INTE_OFFSET 0x0000002c ++#define RPI_MIPICFG_INTE_BITS 0x0000000f ++#define RPI_MIPICFG_INTE_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTE_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTE_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTE_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTE_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTE_DSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTE_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTE_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTE_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTE_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTE_CSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTE_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTE_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTE_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTE_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTE_DSI_DMA_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTE_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTE_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTE_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTE_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTE_CSI_DMA_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTF ++// JTAG access : synchronous ++// Description : Interrupt Force ++#define RPI_MIPICFG_INTF_OFFSET 0x00000030 ++#define RPI_MIPICFG_INTF_BITS 0x0000000f ++#define RPI_MIPICFG_INTF_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTF_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTF_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTF_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTF_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTF_DSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTF_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTF_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTF_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTF_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTF_CSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTF_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTF_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTF_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTF_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTF_DSI_DMA_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTF_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTF_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTF_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTF_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTF_CSI_DMA_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTS ++// JTAG access : synchronous ++// Description : Interrupt status after masking & forcing ++#define RPI_MIPICFG_INTS_OFFSET 0x00000034 ++#define RPI_MIPICFG_INTS_BITS 0x0000000f ++#define RPI_MIPICFG_INTS_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTS_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTS_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTS_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTS_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTS_DSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTS_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTS_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTS_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTS_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTS_CSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTS_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTS_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTS_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTS_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTS_DSI_DMA_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTS_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTS_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTS_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTS_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTS_CSI_DMA_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_BLOCK_ID ++// JTAG access : asynchronous ++// Description : Block Identifier ++#define RPI_MIPICFG_BLOCK_ID_OFFSET 0x00000038 ++#define RPI_MIPICFG_BLOCK_ID_BITS 0xffffffff ++#define RPI_MIPICFG_BLOCK_ID_RESET 0x4d495049 ++#define RPI_MIPICFG_BLOCK_ID_MSB 31 ++#define RPI_MIPICFG_BLOCK_ID_LSB 0 ++#define RPI_MIPICFG_BLOCK_ID_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_INSTANCE_ID ++// JTAG access : asynchronous ++// Description : Block Instance Identifier ++#define RPI_MIPICFG_INSTANCE_ID_OFFSET 0x0000003c ++#define RPI_MIPICFG_INSTANCE_ID_BITS 0x0000000f ++#define RPI_MIPICFG_INSTANCE_ID_RESET 0x00000000 ++#define RPI_MIPICFG_INSTANCE_ID_MSB 3 ++#define RPI_MIPICFG_INSTANCE_ID_LSB 0 ++#define RPI_MIPICFG_INSTANCE_ID_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_AUTO ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_AUTO_OFFSET 0x00000040 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_AUTO_RESET 0x00000007 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_AUTO_CSI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_AUTO_DPI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_PARALLEL ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_OFFSET 0x00000044 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_RESET 0x00000006 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_PARALLEL_CSI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_PARALLEL_DPI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_CTRL ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_CTRL_OFFSET 0x00000048 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_CTRL_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_CTRL_CSI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_CTRL_DPI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_TRIG ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_TRIG_OFFSET 0x0000004c ++#define RPI_MIPICFG_RSTSEQ_TRIG_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_TRIG_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_TRIG_CSI ++// Description : Pulses the reset output ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_ACCESS "SC" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_TRIG_DPI ++// Description : Pulses the reset output ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_ACCESS "SC" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER ++// Description : Pulses the reset output ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_ACCESS "SC" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_DONE ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_DONE_OFFSET 0x00000050 ++#define RPI_MIPICFG_RSTSEQ_DONE_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_DONE_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_DONE_CSI ++// Description : Indicates the current state of the reset ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_DONE_DPI ++// Description : Indicates the current state of the reset ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER ++// Description : Indicates the current state of the reset ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_DFTSS ++// JTAG access : asynchronous ++// Description : None ++#define RPI_MIPICFG_DFTSS_OFFSET 0x00000054 ++#define RPI_MIPICFG_DFTSS_BITS 0x0000001f ++#define RPI_MIPICFG_DFTSS_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_JTAG_COPY ++// Description : None ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_BITS 0x00000010 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_MSB 4 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_LSB 4 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY ++// Description : None ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_BITS 0x00000008 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_MSB 3 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_LSB 3 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS ++// Description : None ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_BITS 0x00000004 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_MSB 2 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_LSB 2 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_BYPASS_INSYNCS ++// Description : None ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_BITS 0x00000002 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_MSB 1 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_LSB 1 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS ++// Description : None ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_BITS 0x00000001 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_MSB 0 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_LSB 0 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_ACCESS "RW" ++ ++#define CFG_WRITE(reg, val) writel((val), dsi->hw_base[RP1DSI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++#define CFG_READ(reg) readl(dsi->hw_base[RP1DSI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++ ++/* ------------------------------- DPHY setup stuff ------------------------ */ ++ ++static void dphy_transaction(struct rp1_dsi *dsi, uint8_t test_code, uint8_t test_data) ++{ ++ /* ++ * See pg 101 of mipi dphy bidir databook ++ * Assume we start with testclk high. ++ * Each APB write takes at least 10ns and we ignore TESTDOUT ++ * so there is no need for extra delays between the transitions. ++ */ ++ u32 tmp; ++ ++ DSI_WRITE(DSI_PHY_TST_CTRL1, test_code | DPHY_CTRL1_PHY_TESTEN_BITS); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, 0); ++ tmp = (DSI_READ(DSI_PHY_TST_CTRL1) >> DPHY_CTRL1_PHY_TESTDOUT_LSB) & 0xFF; ++ DSI_WRITE(DSI_PHY_TST_CTRL1, test_data); ++ 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) ++{ ++ /* ++ * See pg 77-78 of dphy databook ++ * fvco = m/n * refclk ++ * with the limit ++ * 40MHz >= fREFCLK / N >= 5MHz ++ * M (multiplier) must be an even number between 2 and 300 ++ * N (input divider) must be an integer between 1 and 100 ++ * ++ * 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. ++ */ ++ ++ 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; ++ ++ 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); ++ ++ 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; ++ ++ if (err < best_err) { ++ best_n = n; ++ best_m = 2 * half_m; ++ best_err = err; ++ if (err == 0) ++ break; ++ } ++ } ++ } ++ ++ if (64 * best_err < vco_freq_khz) { /* tolerate small error */ ++ *ptr_n = best_n; ++ *ptr_m = best_m; ++ return 1; ++ } ++ return 0; ++} ++ ++struct hsfreq_range { ++ u16 mhz_max; ++ u8 hsfreqrange; ++ u8 clk_lp2hs; ++ u8 clk_hs2lp; ++ u8 data_lp2hs; /* excluding clk lane entry */ ++ u8 data_hs2lp; ++}; ++ ++/* See Table A-3 on page 258 of dphy databook */ ++static const struct hsfreq_range hsfreq_table[] = { ++ { 89, 0b000000, 32, 20, 26, 13 }, ++ { 99, 0b010000, 35, 23, 28, 14 }, ++ { 109, 0b100000, 32, 22, 26, 13 }, ++ { 129, 0b000001, 31, 20, 27, 13 }, ++ { 139, 0b010001, 33, 22, 26, 14 }, ++ { 149, 0b100001, 33, 21, 26, 14 }, ++ { 169, 0b000010, 32, 20, 27, 13 }, ++ { 179, 0b010010, 36, 23, 30, 15 }, ++ { 199, 0b100010, 40, 22, 33, 15 }, ++ { 219, 0b000011, 40, 22, 33, 15 }, ++ { 239, 0b010011, 44, 24, 36, 16 }, ++ { 249, 0b100011, 48, 24, 38, 17 }, ++ { 269, 0b000100, 48, 24, 38, 17 }, ++ { 299, 0b010100, 50, 27, 41, 18 }, ++ { 329, 0b000101, 56, 28, 45, 18 }, ++ { 359, 0b010101, 59, 28, 48, 19 }, ++ { 399, 0b100101, 61, 30, 50, 20 }, ++ { 449, 0b000110, 67, 31, 55, 21 }, ++ { 499, 0b010110, 73, 31, 59, 22 }, ++ { 549, 0b000111, 79, 36, 63, 24 }, ++ { 599, 0b010111, 83, 37, 68, 25 }, ++ { 649, 0b001000, 90, 38, 73, 27 }, ++ { 699, 0b011000, 95, 40, 77, 28 }, ++ { 749, 0b001001, 102, 40, 84, 28 }, ++ { 799, 0b011001, 106, 42, 87, 30 }, ++ { 849, 0b101001, 113, 44, 93, 31 }, ++ { 899, 0b111001, 118, 47, 98, 32 }, ++ { 949, 0b001010, 124, 47, 102, 34 }, ++ { 999, 0b011010, 130, 49, 107, 35 }, ++ { 1049, 0b101010, 135, 51, 111, 37 }, ++ { 1099, 0b111010, 139, 51, 114, 38 }, ++ { 1149, 0b001011, 146, 54, 120, 40 }, ++ { 1199, 0b011011, 153, 57, 125, 41 }, ++ { 1249, 0b101011, 158, 58, 130, 42 }, ++ { 1299, 0b111011, 163, 58, 135, 44 }, ++ { 1349, 0b001100, 168, 60, 140, 45 }, ++ { 1399, 0b011100, 172, 64, 144, 47 }, ++ { 1449, 0b101100, 176, 65, 148, 48 }, ++ { 1500, 0b111100, 181, 66, 153, 50 }, ++}; ++ ++static void dphy_set_hsfreqrange(struct rp1_dsi *dsi, u32 freq_mhz) ++{ ++ unsigned int i; ++ ++ if (freq_mhz < 80 || freq_mhz > 1500) ++ drm_err(dsi->drm, "DPHY: Frequency %u MHz out of range\n", ++ freq_mhz); ++ ++ for (i = 0; i < ARRAY_SIZE(hsfreq_table) - 1; i++) { ++ if (freq_mhz <= hsfreq_table[i].mhz_max) ++ break; ++ } ++ ++ dsi->hsfreq_index = i; ++ dphy_transaction(dsi, DPHY_HS_RX_CTRL_LANE0_OFFSET, ++ hsfreq_table[i].hsfreqrange << 1); ++} ++ ++static void dphy_configure_pll(struct rp1_dsi *dsi, u32 refclk_khz, u32 vco_freq_khz) ++{ ++ u32 m = 0; ++ u32 n = 0; ++ ++ if (dphy_get_div(refclk_khz, vco_freq_khz, &m, &n)) { ++ dphy_set_hsfreqrange(dsi, vco_freq_khz / 1000); ++ /* Program m,n from registers */ ++ dphy_transaction(dsi, DPHY_PLL_DIV_CTRL_OFFSET, 0x30); ++ /* N (program N-1) */ ++ dphy_transaction(dsi, DPHY_PLL_INPUT_DIV_OFFSET, n - 1); ++ /* M[8:5] ?? */ ++ dphy_transaction(dsi, DPHY_PLL_LOOP_DIV_OFFSET, 0x80 | ((m - 1) >> 5)); ++ /* 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); ++ } else { ++ drm_info(dsi->drm, ++ "rp1dsi: Error configuring DPHY PLL! %dkHz = %d * (%dkHz / %d)\r\n", ++ vco_freq_khz, m, refclk_khz, n); ++ } ++} ++ ++static void dphy_init_khz(struct rp1_dsi *dsi, u32 ref_freq, u32 vco_freq) ++{ ++ /* Reset the PHY */ ++ DSI_WRITE(DSI_PHYRSTZ, 0); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS); ++ DSI_WRITE(DSI_PHY_TST_CTRL1, 0); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, (DPHY_CTRL0_PHY_TESTCLK_BITS | DPHY_CTRL0_PHY_TESTCLR_BITS)); ++ udelay(1); ++ 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); ++ 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? */ ++} ++ ++void rp1dsi_mipicfg_setup(struct rp1_dsi *dsi) ++{ ++ /* Select DSI rather than CSI-2 */ ++ CFG_WRITE(RPI_MIPICFG_CFG, 0); ++ /* Enable DSIDMA interrupt only */ ++ CFG_WRITE(RPI_MIPICFG_INTE, RPI_MIPICFG_INTE_DSI_DMA_BITS); ++} ++ ++static unsigned long rp1dsi_refclk_freq(struct rp1_dsi *dsi) ++{ ++ unsigned long u; ++ ++ u = (dsi->clocks[RP1DSI_CLOCK_REF]) ? clk_get_rate(dsi->clocks[RP1DSI_CLOCK_REF]) : 0; ++ if (u < 1 || u >= (1ul << 30)) ++ u = 50000000ul; /* default XOSC frequency */ ++ return u; ++} ++ ++static void rp1dsi_dpiclk_start(struct rp1_dsi *dsi, 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 */ ++ ++ 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]); ++ } ++} ++ ++static void rp1dsi_dpiclk_stop(struct rp1_dsi *dsi) ++{ ++ if (dsi->clocks[RP1DSI_CLOCK_DPI]) ++ clk_disable_unprepare(dsi->clocks[RP1DSI_CLOCK_DPI]); ++} ++ ++/* Choose the internal on-the-bus DPI format, and DSI packing flag. */ ++static u32 get_colorcode(enum mipi_dsi_pixel_format fmt) ++{ ++ switch (fmt) { ++ case MIPI_DSI_FMT_RGB666: ++ return 0x104; ++ case MIPI_DSI_FMT_RGB666_PACKED: ++ return 0x003; ++ case MIPI_DSI_FMT_RGB565: ++ return 0x000; ++ case MIPI_DSI_FMT_RGB888: ++ return 0x005; ++ } ++ ++ /* This should be impossible as the format is validated in ++ * rp1dsi_host_attach ++ */ ++ WARN_ONCE(1, "Invalid colour format configured for DSI"); ++ return 0x005; ++} ++ ++void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode) ++{ ++ u32 timeout, mask, vid_mode_cfg; ++ u32 freq_khz; ++ unsigned int bpp = mipi_dsi_pixel_format_to_bpp(dsi->display_format); ++ ++ DSI_WRITE(DSI_PHY_IF_CFG, dsi->lanes - 1); ++ DSI_WRITE(DSI_DPI_CFG_POL, 0); ++ DSI_WRITE(DSI_GEN_VCID, dsi->vc); ++ DSI_WRITE(DSI_DPI_COLOR_CODING, get_colorcode(dsi->display_format)); ++ /* a conservative guess (LP escape is slow!) */ ++ DSI_WRITE(DSI_DPI_LP_CMD_TIM, 0x00100000); ++ ++ /* Drop to LP where possible */ ++ vid_mode_cfg = 0xbf00; ++ if (!(dsi->display_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) ++ vid_mode_cfg |= 0x01; ++ if (dsi->display_flags & MIPI_DSI_MODE_VIDEO_BURST) ++ vid_mode_cfg |= 0x02; ++ DSI_WRITE(DSI_VID_MODE_CFG, vid_mode_cfg); ++ ++ /* Use LP Escape Data signalling for all commands */ ++ DSI_WRITE(DSI_CMD_MODE_CFG, 0x10F7F00); ++ /* Select Command Mode */ ++ DSI_WRITE(DSI_MODE_CFG, 1); ++ /* XXX magic number */ ++ DSI_WRITE(DSI_TO_CNT_CFG, 0x02000200); ++ /* XXX magic number */ ++ DSI_WRITE(DSI_BTA_TO_CNT, 0x800); ++ ++ DSI_WRITE(DSI_VID_PKT_SIZE, mode->hdisplay); ++ DSI_WRITE(DSI_VID_NUM_CHUNKS, 0); ++ DSI_WRITE(DSI_VID_NULL_SIZE, 0); ++ ++ /* Note, unlike Argon firmware, here we DON'T consider sync to be concurrent with porch */ ++ DSI_WRITE(DSI_VID_HSA_TIME, ++ (bpp * (mode->hsync_end - mode->hsync_start)) / (8 * dsi->lanes)); ++ DSI_WRITE(DSI_VID_HBP_TIME, ++ (bpp * (mode->htotal - mode->hsync_end)) / (8 * dsi->lanes)); ++ DSI_WRITE(DSI_VID_HLINE_TIME, (bpp * mode->htotal) / (8 * dsi->lanes)); ++ DSI_WRITE(DSI_VID_VSA_LINES, (mode->vsync_end - mode->vsync_start)); ++ DSI_WRITE(DSI_VID_VBP_LINES, (mode->vtotal - mode->vsync_end)); ++ DSI_WRITE(DSI_VID_VFP_LINES, (mode->vsync_start - mode->vdisplay)); ++ DSI_WRITE(DSI_VID_VACTIVE_LINES, mode->vdisplay); ++ ++ freq_khz = (bpp * mode->clock) / dsi->lanes; ++ ++ dphy_init_khz(dsi, rp1dsi_refclk_freq(dsi) / 1000, freq_khz); ++ ++ DSI_WRITE(DSI_PHY_TMR_LPCLK_CFG, ++ (hsfreq_table[dsi->hsfreq_index].clk_lp2hs << DSI_PHY_TMR_LP2HS_LSB) | ++ (hsfreq_table[dsi->hsfreq_index].clk_hs2lp << DSI_PHY_TMR_HS2LP_LSB)); ++ DSI_WRITE(DSI_PHY_TMR_CFG, ++ (hsfreq_table[dsi->hsfreq_index].data_lp2hs << DSI_PHY_TMR_LP2HS_LSB) | ++ (hsfreq_table[dsi->hsfreq_index].data_hs2lp << DSI_PHY_TMR_HS2LP_LSB)); ++ ++ DSI_WRITE(DSI_CLKMGR_CFG, 0x00000505); ++ ++ /* Wait for PLL lock */ ++ for (timeout = (1 << 14); timeout != 0; --timeout) { ++ usleep_range(10, 50); ++ if (DSI_READ(DSI_PHY_STATUS) & (1 << 0)) ++ break; ++ } ++ if (timeout == 0) ++ drm_err(dsi->drm, "RP1DSI: Time out waiting for PLL\n"); ++ ++ DSI_WRITE(DSI_LPCLK_CTRL, 0x1); /* configure the requesthsclk */ ++ DSI_WRITE(DSI_PHY_TST_CTRL0, 0x2); ++ DSI_WRITE(DSI_PCKHDL_CFG, 1 << 2); /* allow bus turnaround */ ++ 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); ++ ++ /* Wait for all lane(s) to be in Stopstate */ ++ mask = (1 << 4); ++ if (dsi->lanes >= 2) ++ mask |= (1 << 7); ++ if (dsi->lanes >= 3) ++ mask |= (1 << 9); ++ if (dsi->lanes >= 4) ++ mask |= (1 << 11); ++ for (timeout = (1 << 10); timeout != 0; --timeout) { ++ usleep_range(10, 50); ++ if ((DSI_READ(DSI_PHY_STATUS) & mask) == mask) ++ break; ++ } ++ if (timeout == 0) ++ drm_err(dsi->drm, "RP1DSI: Time out waiting for lanes (%x %x)\n", ++ mask, DSI_READ(DSI_PHY_STATUS)); ++} ++ ++void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 hdr, int len, const u8 *buf) ++{ ++ u32 val; ++ ++ /* Wait for both FIFOs empty */ ++ for (val = 256; val > 0; --val) { ++ if ((DSI_READ(DSI_CMD_PKT_STATUS) & 0xF) == 0x5) ++ break; ++ usleep_range(100, 150); ++ } ++ ++ /* Write payload (in 32-bit words) and header */ ++ for (; len > 0; len -= 4) { ++ val = *buf++; ++ if (len > 1) ++ val |= (*buf++) << 8; ++ if (len > 2) ++ val |= (*buf++) << 16; ++ if (len > 3) ++ val |= (*buf++) << 24; ++ DSI_WRITE(DSI_GEN_PLD_DATA, val); ++ } ++ DSI_WRITE(DSI_GEN_HDR, hdr); ++ ++ /* Wait for both FIFOs empty */ ++ for (val = 256; val > 0; --val) { ++ if ((DSI_READ(DSI_CMD_PKT_STATUS) & 0xF) == 0x5) ++ break; ++ usleep_range(100, 150); ++ } ++} ++ ++int rp1dsi_dsi_recv(struct rp1_dsi *dsi, int len, u8 *buf) ++{ ++ int i, j; ++ u32 val; ++ ++ /* Wait until not busy and FIFO not empty */ ++ for (i = 1024; i > 0; --i) { ++ val = DSI_READ(DSI_CMD_PKT_STATUS); ++ if ((val & ((1 << 6) | (1 << 4))) == 0) ++ break; ++ usleep_range(100, 150); ++ } ++ if (i == 0) ++ return -EIO; ++ ++ for (i = 0; i < len; i += 4) { ++ /* Read fifo must not be empty before all bytes are read */ ++ if (DSI_READ(DSI_CMD_PKT_STATUS) & (1 << 4)) ++ break; ++ ++ val = DSI_READ(DSI_GEN_PLD_DATA); ++ for (j = 0; j < 4 && j + i < len; j++) ++ *buf++ = val >> (8 * j); ++ } ++ ++ return (i >= len) ? len : (i > 0) ? i : -EIO; ++} ++ ++void rp1dsi_dsi_stop(struct rp1_dsi *dsi) ++{ ++ DSI_WRITE(DSI_MODE_CFG, 1); /* Return to Command Mode */ ++ DSI_WRITE(DSI_LPCLK_CTRL, 2); /* Stop the HS clock */ ++ DSI_WRITE(DSI_PWR_UP, 0x0); /* Power down host controller */ ++ DSI_WRITE(DSI_PHYRSTZ, 0); /* PHY into reset. */ ++ rp1dsi_dpiclk_stop(dsi); ++} ++ ++void rp1dsi_dsi_set_cmdmode(struct rp1_dsi *dsi, int mode) ++{ ++ DSI_WRITE(DSI_MODE_CFG, mode); ++} diff --git a/target/linux/bcm27xx/patches-6.1/950-0886-drm-Add-RP1-DPI-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0886-drm-Add-RP1-DPI-driver.patch new file mode 100644 index 0000000000..2023bf73e8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0886-drm-Add-RP1-DPI-driver.patch @@ -0,0 +1,1552 @@ +From 61c3065f89d4447c7e4cf61a466ebc3c4a834ad2 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Tue, 19 Sep 2023 17:51:49 +0100 +Subject: [PATCH] drm: Add RP1 DPI driver + +Add support for the RP1 DPI hardware. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/rp1/rp1-dpi/Kconfig | 12 + + drivers/gpu/drm/rp1/rp1-dpi/Makefile | 5 + + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c | 429 ++++++++++++++++++ + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h | 69 +++ + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c | 510 ++++++++++++++++++++++ + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c | 486 +++++++++++++++++++++ + 6 files changed, 1511 insertions(+) + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/Kconfig + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c + +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/Kconfig +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config DRM_RP1_DPI ++ tristate "DRM Support for RP1 DPI" ++ depends on DRM ++ select MFD_RP1 ++ select DRM_GEM_DMA_HELPER ++ select DRM_KMS_HELPER ++ select DRM_VRAM_HELPER ++ select DRM_TTM ++ select DRM_TTM_HELPER ++ help ++ Choose this option to enable Video Out on RP1 +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++drm-rp1-dpi-y := rp1_dpi.o rp1_dpi_hw.o rp1_dpi_cfg.o ++ ++obj-$(CONFIG_DRM_RP1_DPI) += drm-rp1-dpi.o +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c +@@ -0,0 +1,429 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DPI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dpi.h" ++ ++/* ++ * Default bus format, where not specified by a connector/bridge ++ * and not overridden by the OF property "default_bus_fmt". ++ * This value is for compatibility with vc4 and VGA666-style boards, ++ * even though RP1 hardware cannot achieve the full 18-bit depth ++ * with that pinout (MEDIA_BUS_FMT_RGB666_1X24_CPADHI is preferred). ++ */ ++static unsigned int default_bus_fmt = MEDIA_BUS_FMT_RGB666_1X18; ++module_param(default_bus_fmt, uint, 0644); ++ ++/* -------------------------------------------------------------- */ ++ ++static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe, ++ struct drm_plane_state *old_state) ++{ ++ struct drm_pending_vblank_event *event; ++ unsigned long flags; ++ struct drm_framebuffer *fb = pipe->plane.state->fb; ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ struct drm_gem_object *gem = fb ? drm_gem_fb_get_obj(fb, 0) : NULL; ++ struct drm_gem_dma_object *dma_obj = gem ? to_drm_gem_dma_obj(gem) : NULL; ++ bool can_update = fb && dma_obj && dpi && dpi->pipe_enabled; ++ ++ /* (Re-)start DPI-DMA where required; and update FB address */ ++ if (can_update) { ++ if (!dpi->dpi_running || fb->format->format != dpi->cur_fmt) { ++ if (dpi->dpi_running && ++ fb->format->format != dpi->cur_fmt) { ++ rp1dpi_hw_stop(dpi); ++ dpi->dpi_running = false; ++ } ++ if (!dpi->dpi_running) { ++ rp1dpi_hw_setup(dpi, ++ fb->format->format, ++ dpi->bus_fmt, ++ dpi->de_inv, ++ &pipe->crtc.state->mode); ++ dpi->dpi_running = true; ++ } ++ dpi->cur_fmt = fb->format->format; ++ drm_crtc_vblank_on(&pipe->crtc); ++ } ++ rp1dpi_hw_update(dpi, dma_obj->dma_addr, fb->offsets[0], fb->pitches[0]); ++ } ++ ++ /* Arm VBLANK event (or call it immediately in some error cases) */ ++ spin_lock_irqsave(&pipe->crtc.dev->event_lock, flags); ++ event = pipe->crtc.state->event; ++ if (event) { ++ pipe->crtc.state->event = NULL; ++ if (can_update && drm_crtc_vblank_get(&pipe->crtc) == 0) ++ drm_crtc_arm_vblank_event(&pipe->crtc, event); ++ else ++ drm_crtc_send_vblank_event(&pipe->crtc, event); ++ } ++ spin_unlock_irqrestore(&pipe->crtc.dev->event_lock, flags); ++} ++ ++static void rp1dpi_pipe_enable(struct drm_simple_display_pipe *pipe, ++ struct drm_crtc_state *crtc_state, ++ struct drm_plane_state *plane_state) ++{ ++ static const unsigned int M = 1000000; ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ struct drm_connector *conn; ++ struct drm_connector_list_iter conn_iter; ++ unsigned int fpix, fdiv, fvco; ++ int ret; ++ ++ /* Look up the connector attached to DPI so we can get the ++ * bus_format. Ideally the bridge would tell us the ++ * bus_format we want, but it doesn't yet, so assume that it's ++ * uniform throughout the bridge chain. ++ */ ++ dev_info(&dpi->pdev->dev, __func__); ++ drm_connector_list_iter_begin(pipe->encoder.dev, &conn_iter); ++ drm_for_each_connector_iter(conn, &conn_iter) { ++ if (conn->encoder == &pipe->encoder) { ++ dpi->de_inv = !!(conn->display_info.bus_flags & ++ DRM_BUS_FLAG_DE_LOW); ++ dpi->clk_inv = !!(conn->display_info.bus_flags & ++ DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE); ++ if (conn->display_info.num_bus_formats) ++ dpi->bus_fmt = conn->display_info.bus_formats[0]; ++ break; ++ } ++ } ++ drm_connector_list_iter_end(&conn_iter); ++ ++ /* Set DPI clock to desired frequency. Currently (experimentally) ++ * we take control of the VideoPLL, to ensure we can generate it ++ * accurately. NB: this prevents concurrent use of DPI and VEC! ++ * Magic numbers ensure the parent clock is within [100MHz, 200MHz] ++ * with VCO in [1GHz, 1.33GHz]. The initial divide is by 6, 8 or 10. ++ */ ++ fpix = 1000 * pipe->crtc.state->mode.clock; ++ fpix = clamp(fpix, 1 * M, 200 * M); ++ fdiv = fpix; ++ while (fdiv < 100 * M) ++ fdiv *= 2; ++ fvco = fdiv * 2 * DIV_ROUND_UP(500 * M, fdiv); ++ ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_PLLCORE], fvco); ++ if (ret) ++ dev_err(&dpi->pdev->dev, "Failed to set PLL VCO to %u (%d)", fvco, ret); ++ ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_PLLDIV], fdiv); ++ if (ret) ++ dev_err(&dpi->pdev->dev, "Failed to set PLL output to %u (%d)", fdiv, ret); ++ ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_DPI], fpix); ++ if (ret) ++ dev_err(&dpi->pdev->dev, "Failed to set DPI clock to %u (%d)", fpix, ret); ++ ++ rp1dpi_vidout_setup(dpi, dpi->clk_inv); ++ clk_prepare_enable(dpi->clocks[RP1DPI_CLK_PLLCORE]); ++ clk_prepare_enable(dpi->clocks[RP1DPI_CLK_PLLDIV]); ++ pinctrl_pm_select_default_state(&dpi->pdev->dev); ++ clk_prepare_enable(dpi->clocks[RP1DPI_CLK_DPI]); ++ dev_info(&dpi->pdev->dev, "Want %u /%u %u /%u %u; got VCO=%lu DIV=%lu DPI=%lu", ++ fvco, fvco / fdiv, fdiv, fdiv / fpix, fpix, ++ clk_get_rate(dpi->clocks[RP1DPI_CLK_PLLCORE]), ++ clk_get_rate(dpi->clocks[RP1DPI_CLK_PLLDIV]), ++ clk_get_rate(dpi->clocks[RP1DPI_CLK_DPI])); ++ ++ /* Start DPI-DMA. pipe already has the new crtc and plane state. */ ++ dpi->pipe_enabled = true; ++ dpi->cur_fmt = 0xdeadbeef; ++ rp1dpi_pipe_update(pipe, 0); ++} ++ ++static void rp1dpi_pipe_disable(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ ++ dev_info(&dpi->pdev->dev, __func__); ++ drm_crtc_vblank_off(&pipe->crtc); ++ if (dpi->dpi_running) { ++ rp1dpi_hw_stop(dpi); ++ dpi->dpi_running = false; ++ } ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]); ++ pinctrl_pm_select_sleep_state(&dpi->pdev->dev); ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_PLLDIV]); ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_PLLCORE]); ++ dpi->pipe_enabled = false; ++} ++ ++static int rp1dpi_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ ++ if (dpi) ++ rp1dpi_hw_vblank_ctrl(dpi, 1); ++ ++ return 0; ++} ++ ++static void rp1dpi_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ ++ if (dpi) ++ rp1dpi_hw_vblank_ctrl(dpi, 0); ++} ++ ++static const struct drm_simple_display_pipe_funcs rp1dpi_pipe_funcs = { ++ .enable = rp1dpi_pipe_enable, ++ .update = rp1dpi_pipe_update, ++ .disable = rp1dpi_pipe_disable, ++ .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, ++ .enable_vblank = rp1dpi_pipe_enable_vblank, ++ .disable_vblank = rp1dpi_pipe_disable_vblank, ++}; ++ ++static const struct drm_mode_config_funcs rp1dpi_mode_funcs = { ++ .fb_create = drm_gem_fb_create, ++ .atomic_check = drm_atomic_helper_check, ++ .atomic_commit = drm_atomic_helper_commit, ++}; ++ ++static void rp1dpi_stopall(struct drm_device *drm) ++{ ++ if (drm->dev_private) { ++ struct rp1_dpi *dpi = drm->dev_private; ++ ++ if (dpi->dpi_running || rp1dpi_hw_busy(dpi)) { ++ rp1dpi_hw_stop(dpi); ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]); ++ dpi->dpi_running = false; ++ } ++ rp1dpi_vidout_poweroff(dpi); ++ pinctrl_pm_select_sleep_state(&dpi->pdev->dev); ++ } ++} ++ ++DEFINE_DRM_GEM_DMA_FOPS(rp1dpi_fops); ++ ++static struct drm_driver rp1dpi_driver = { ++ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, ++ .fops = &rp1dpi_fops, ++ .name = "drm-rp1-dpi", ++ .desc = "drm-rp1-dpi", ++ .date = "0", ++ .major = 1, ++ .minor = 0, ++ DRM_GEM_DMA_DRIVER_OPS, ++ .release = rp1dpi_stopall, ++}; ++ ++static const u32 rp1dpi_formats[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565 ++}; ++ ++static int rp1dpi_platform_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct drm_device *drm; ++ struct rp1_dpi *dpi; ++ struct drm_bridge *bridge = NULL; ++ struct drm_panel *panel; ++ int i, ret; ++ ++ dev_info(dev, __func__); ++ ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 0, 0, ++ &panel, &bridge); ++ if (ret) { ++ dev_info(dev, "%s: bridge not found\n", __func__); ++ return -EPROBE_DEFER; ++ } ++ if (panel) { ++ bridge = devm_drm_panel_bridge_add(dev, panel); ++ if (IS_ERR(bridge)) ++ return PTR_ERR(bridge); ++ } ++ ++ drm = drm_dev_alloc(&rp1dpi_driver, dev); ++ if (IS_ERR(drm)) { ++ dev_info(dev, "%s %d", __func__, (int)__LINE__); ++ ret = PTR_ERR(drm); ++ return ret; ++ } ++ dpi = drmm_kzalloc(drm, sizeof(*dpi), GFP_KERNEL); ++ if (!dpi) { ++ dev_info(dev, "%s %d", __func__, (int)__LINE__); ++ drm_dev_put(drm); ++ return -ENOMEM; ++ } ++ ++ init_completion(&dpi->finished); ++ dpi->drm = drm; ++ dpi->pdev = pdev; ++ drm->dev_private = dpi; ++ platform_set_drvdata(pdev, drm); ++ ++ dpi->bus_fmt = default_bus_fmt; ++ ret = of_property_read_u32(dev->of_node, "default_bus_fmt", &dpi->bus_fmt); ++ ++ for (i = 0; i < RP1DPI_NUM_HW_BLOCKS; i++) { ++ dpi->hw_base[i] = ++ devm_ioremap_resource(dev, ++ platform_get_resource(dpi->pdev, IORESOURCE_MEM, i)); ++ if (IS_ERR(dpi->hw_base[i])) { ++ ret = PTR_ERR(dpi->hw_base[i]); ++ dev_err(dev, "Error memory mapping regs[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ret = platform_get_irq(dpi->pdev, 0); ++ if (ret > 0) ++ ret = devm_request_irq(dev, ret, rp1dpi_hw_isr, ++ IRQF_SHARED, "rp1-dpi", dpi); ++ if (ret) { ++ dev_err(dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_free_drm; ++ } ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); ++ ++ for (i = 0; i < RP1DPI_NUM_CLOCKS; i++) { ++ static const char * const myclocknames[RP1DPI_NUM_CLOCKS] = { ++ "dpiclk", "plldiv", "pllcore" ++ }; ++ dpi->clocks[i] = devm_clk_get(dev, myclocknames[i]); ++ if (IS_ERR(dpi->clocks[i])) { ++ ret = PTR_ERR(dpi->clocks[i]); ++ goto err_free_drm; ++ } ++ } ++ ++ ret = drmm_mode_config_init(drm); ++ if (ret) ++ goto err_free_drm; ++ ++ drm->mode_config.max_width = 4096; ++ drm->mode_config.max_height = 4096; ++ drm->mode_config.fb_base = 0; ++ drm->mode_config.preferred_depth = 32; ++ drm->mode_config.prefer_shadow = 0; ++ drm->mode_config.prefer_shadow_fbdev = 1; ++ drm->mode_config.quirk_addfb_prefer_host_byte_order = true; ++ drm->mode_config.funcs = &rp1dpi_mode_funcs; ++ drm_vblank_init(drm, 1); ++ ++ ret = drm_simple_display_pipe_init(drm, ++ &dpi->pipe, ++ &rp1dpi_pipe_funcs, ++ rp1dpi_formats, ++ ARRAY_SIZE(rp1dpi_formats), ++ NULL, NULL); ++ if (!ret) ++ ret = drm_simple_display_pipe_attach_bridge(&dpi->pipe, bridge); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_mode_config_reset(drm); ++ ++ ret = drm_dev_register(drm, 0); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_fbdev_generic_setup(drm, 32); ++ ++ dev_info(dev, "%s success\n", __func__); ++ return ret; ++ ++err_free_drm: ++ dev_err(dev, "%s fail %d\n", __func__, ret); ++ drm_dev_put(drm); ++ return ret; ++} ++ ++static int rp1dpi_platform_remove(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1dpi_stopall(drm); ++ drm_dev_unregister(drm); ++ drm_atomic_helper_shutdown(drm); ++ drm_dev_put(drm); ++ ++ return 0; ++} ++ ++static void rp1dpi_platform_shutdown(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1dpi_stopall(drm); ++} ++ ++static const struct of_device_id rp1dpi_of_match[] = { ++ { ++ .compatible = "raspberrypi,rp1dpi", ++ }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rp1dpi_of_match); ++ ++static struct platform_driver rp1dpi_platform_driver = { ++ .probe = rp1dpi_platform_probe, ++ .remove = rp1dpi_platform_remove, ++ .shutdown = rp1dpi_platform_shutdown, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rp1dpi_of_match, ++ }, ++}; ++ ++module_platform_driver(rp1dpi_platform_driver); ++ ++MODULE_AUTHOR("Nick Hollinghurst"); ++MODULE_DESCRIPTION("DRM driver for DPI output on Raspberry Pi RP1"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h +@@ -0,0 +1,69 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "drm-rp1-dpi" ++#define DRIVER_NAME "drm-rp1-dpi" ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define RP1DPI_HW_BLOCK_DPI 0 ++#define RP1DPI_HW_BLOCK_CFG 1 ++#define RP1DPI_NUM_HW_BLOCKS 2 ++ ++#define RP1DPI_CLK_DPI 0 ++#define RP1DPI_CLK_PLLDIV 1 ++#define RP1DPI_CLK_PLLCORE 2 ++#define RP1DPI_NUM_CLOCKS 3 ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct rp1_dpi { ++ /* DRM and platform device pointers */ ++ struct drm_device *drm; ++ struct platform_device *pdev; ++ ++ /* Framework and helper objects */ ++ struct drm_simple_display_pipe pipe; ++ struct drm_connector connector; ++ ++ /* Clocks: Video PLL, its primary divider, and DPI clock. */ ++ struct clk *clocks[RP1DPI_NUM_CLOCKS]; ++ ++ /* Block (DPI, VOCFG) base addresses, and current state */ ++ void __iomem *hw_base[RP1DPI_NUM_HW_BLOCKS]; ++ u32 cur_fmt; ++ u32 bus_fmt; ++ bool de_inv, clk_inv; ++ bool dpi_running, pipe_enabled; ++ struct completion finished; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the DPI/DMA block */ ++ ++void rp1dpi_hw_setup(struct rp1_dpi *dpi, ++ u32 in_format, ++ u32 bus_format, ++ bool de_inv, ++ struct drm_display_mode const *mode); ++void rp1dpi_hw_update(struct rp1_dpi *dpi, dma_addr_t addr, u32 offset, u32 stride); ++void rp1dpi_hw_stop(struct rp1_dpi *dpi); ++int rp1dpi_hw_busy(struct rp1_dpi *dpi); ++irqreturn_t rp1dpi_hw_isr(int irq, void *dev); ++void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the VIDEO OUT CFG block and check RP1 platform */ ++ ++void rp1dpi_vidout_setup(struct rp1_dpi *dpi, bool drive_negedge); ++void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c +@@ -0,0 +1,510 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DPI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dpi.h" ++ ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_SEL ++// JTAG access : synchronous ++// Description : Selects source: VEC or DPI ++#define VIDEO_OUT_CFG_SEL_OFFSET 0x00000000 ++#define VIDEO_OUT_CFG_SEL_BITS 0x00000013 ++#define VIDEO_OUT_CFG_SEL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PCLK_INV ++// Description : Select dpi_pclk output port polarity inversion. ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_BITS 0x00000010 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_MSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_LSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PAD_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_BITS 0x00000002 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_MSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_LSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_VDAC_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_BITS 0x00000001 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_MSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_LSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_CFG ++// JTAG access : synchronous ++// Description : Configure SNPS VDAC ++#define VIDEO_OUT_CFG_VDAC_CFG_OFFSET 0x00000004 ++#define VIDEO_OUT_CFG_VDAC_CFG_BITS 0x1fffffff ++#define VIDEO_OUT_CFG_VDAC_CFG_RESET 0x0003ffff ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENCTR ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_BITS 0x1c000000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_MSB 28 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_LSB 26 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENSC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_BITS 0x03800000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_MSB 25 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_LSB 23 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENDAC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_BITS 0x00700000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_MSB 22 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_LSB 20 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENVBG ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_BITS 0x00080000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_MSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_LSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_BITS 0x00040000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_MSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_LSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC2GC ++// Description : dac2 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_BITS 0x0003f000 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_MSB 17 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_LSB 12 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC1GC ++// Description : dac1 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_BITS 0x00000fc0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_MSB 11 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_LSB 6 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC0GC ++// Description : dac0 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_BITS 0x0000003f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_MSB 5 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_STATUS ++// JTAG access : synchronous ++// Description : Read VDAC status ++#define VIDEO_OUT_CFG_VDAC_STATUS_OFFSET 0x00000008 ++#define VIDEO_OUT_CFG_VDAC_STATUS_BITS 0x00000017 ++#define VIDEO_OUT_CFG_VDAC_STATUS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3 ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_BITS 0x00000010 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_MSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_LSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_RESET "-" ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_BITS 0x00000007 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_MSB 2 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_MEM_PD ++// JTAG access : synchronous ++// Description : Control memory power down ++#define VIDEO_OUT_CFG_MEM_PD_OFFSET 0x0000000c ++#define VIDEO_OUT_CFG_MEM_PD_BITS 0x00000003 ++#define VIDEO_OUT_CFG_MEM_PD_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_VEC ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_BITS 0x00000002 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_MSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_LSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_DPI ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_BITS 0x00000001 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_MSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_LSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_TEST_OVERRIDE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_OFFSET 0x00000010 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_BITS 0xffffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_PAD ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_BITS 0x80000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_MSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_LSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS 0x40000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_MSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_LSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_RESET 0x00000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_BITS 0x3fffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_MSB 29 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_LSB 0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTR ++// JTAG access : synchronous ++// Description : Raw Interrupts ++#define VIDEO_OUT_CFG_INTR_OFFSET 0x00000014 ++#define VIDEO_OUT_CFG_INTR_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTR_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTR_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTR_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTR_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTR_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTE ++// JTAG access : synchronous ++// Description : Interrupt Enable ++#define VIDEO_OUT_CFG_INTE_OFFSET 0x00000018 ++#define VIDEO_OUT_CFG_INTE_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTE_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTF ++// JTAG access : synchronous ++// Description : Interrupt Force ++#define VIDEO_OUT_CFG_INTF_OFFSET 0x0000001c ++#define VIDEO_OUT_CFG_INTF_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTF_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTF_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTF_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTF_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTF_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTS ++// JTAG access : synchronous ++// Description : Interrupt status after masking & forcing ++#define VIDEO_OUT_CFG_INTS_OFFSET 0x00000020 ++#define VIDEO_OUT_CFG_INTS_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTS_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTS_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTS_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTS_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_BLOCK_ID ++// JTAG access : synchronous ++// Description : Block Identifier ++// Hexadecimal representation of "VOCF" ++#define VIDEO_OUT_CFG_BLOCK_ID_OFFSET 0x00000024 ++#define VIDEO_OUT_CFG_BLOCK_ID_BITS 0xffffffff ++#define VIDEO_OUT_CFG_BLOCK_ID_RESET 0x564f4346 ++#define VIDEO_OUT_CFG_BLOCK_ID_MSB 31 ++#define VIDEO_OUT_CFG_BLOCK_ID_LSB 0 ++#define VIDEO_OUT_CFG_BLOCK_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INSTANCE_ID ++// JTAG access : synchronous ++// Description : Block Instance Identifier ++#define VIDEO_OUT_CFG_INSTANCE_ID_OFFSET 0x00000028 ++#define VIDEO_OUT_CFG_INSTANCE_ID_BITS 0x0000000f ++#define VIDEO_OUT_CFG_INSTANCE_ID_RESET 0x00000000 ++#define VIDEO_OUT_CFG_INSTANCE_ID_MSB 3 ++#define VIDEO_OUT_CFG_INSTANCE_ID_LSB 0 ++#define VIDEO_OUT_CFG_INSTANCE_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_AUTO ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_OFFSET 0x0000002c ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_RESET 0x00000007 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_PARALLEL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_OFFSET 0x00000030 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_RESET 0x00000006 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_CTRL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_OFFSET 0x00000034 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_TRIG ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_OFFSET 0x00000038 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_ACCESS "SC" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_DONE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_OFFSET 0x0000003c ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_VEC ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_DPI ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++ ++#define CFG_WRITE(reg, val) writel((val), dpi->hw_base[RP1DPI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++#define CFG_READ(reg) readl(dpi->hw_base[RP1DPI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++ ++void rp1dpi_vidout_setup(struct rp1_dpi *dpi, bool drive_negedge) ++{ ++ /* ++ * We assume DPI and VEC can't be used at the same time (due to ++ * clashing requirements for PLL_VIDEO, and potentially for VDAC). ++ * We therefore leave VEC memories powered down. ++ */ ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_VEC_BITS); ++ CFG_WRITE(VIDEO_OUT_CFG_TEST_OVERRIDE, ++ VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS); ++ ++ /* DPI->Pads; DPI->VDAC; optionally flip PCLK polarity */ ++ CFG_WRITE(VIDEO_OUT_CFG_SEL, ++ drive_negedge ? VIDEO_OUT_CFG_SEL_PCLK_INV_BITS : 0); ++ ++ /* configure VDAC for 3 channels, bandgap on, 710mV swing */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0); ++ ++ /* enable DPI interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, VIDEO_OUT_CFG_INTE_DPI_BITS); ++} ++ ++void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi) ++{ ++ /* disable DPI interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, 0); ++ ++ /* Ensure VDAC is turned off; power down DPI,VEC memories */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0); ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_BITS); ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c +@@ -0,0 +1,486 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DPI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dpi.h" ++ ++// --- DPI DMA REGISTERS --- ++ ++// Control ++#define DPI_DMA_CONTROL 0x0 ++#define DPI_DMA_CONTROL_ARM_SHIFT 0 ++#define DPI_DMA_CONTROL_ARM_MASK BIT(DPI_DMA_CONTROL_ARM_SHIFT) ++#define DPI_DMA_CONTROL_ALIGN16_SHIFT 2 ++#define DPI_DMA_CONTROL_ALIGN16_MASK BIT(DPI_DMA_CONTROL_ALIGN16_SHIFT) ++#define DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT 1 ++#define DPI_DMA_CONTROL_AUTO_REPEAT_MASK BIT(DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT) ++#define DPI_DMA_CONTROL_HIGH_WATER_SHIFT 3 ++#define DPI_DMA_CONTROL_HIGH_WATER_MASK (0x1FF << DPI_DMA_CONTROL_HIGH_WATER_SHIFT) ++#define DPI_DMA_CONTROL_DEN_POL_SHIFT 12 ++#define DPI_DMA_CONTROL_DEN_POL_MASK BIT(DPI_DMA_CONTROL_DEN_POL_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_POL_SHIFT 13 ++#define DPI_DMA_CONTROL_HSYNC_POL_MASK BIT(DPI_DMA_CONTROL_HSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_POL_SHIFT 14 ++#define DPI_DMA_CONTROL_VSYNC_POL_MASK BIT(DPI_DMA_CONTROL_VSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_COLORM_SHIFT 15 ++#define DPI_DMA_CONTROL_COLORM_MASK BIT(DPI_DMA_CONTROL_COLORM_SHIFT) ++#define DPI_DMA_CONTROL_SHUTDN_SHIFT 16 ++#define DPI_DMA_CONTROL_SHUTDN_MASK BIT(DPI_DMA_CONTROL_SHUTDN_SHIFT) ++#define DPI_DMA_CONTROL_HBP_EN_SHIFT 17 ++#define DPI_DMA_CONTROL_HBP_EN_MASK BIT(DPI_DMA_CONTROL_HBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HFP_EN_SHIFT 18 ++#define DPI_DMA_CONTROL_HFP_EN_MASK BIT(DPI_DMA_CONTROL_HFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VBP_EN_SHIFT 19 ++#define DPI_DMA_CONTROL_VBP_EN_MASK BIT(DPI_DMA_CONTROL_VBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VFP_EN_SHIFT 20 ++#define DPI_DMA_CONTROL_VFP_EN_MASK BIT(DPI_DMA_CONTROL_VFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_EN_SHIFT 21 ++#define DPI_DMA_CONTROL_HSYNC_EN_MASK BIT(DPI_DMA_CONTROL_HSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_EN_SHIFT 22 ++#define DPI_DMA_CONTROL_VSYNC_EN_MASK BIT(DPI_DMA_CONTROL_VSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_IMMED_SHIFT 23 ++#define DPI_DMA_CONTROL_FORCE_IMMED_MASK BIT(DPI_DMA_CONTROL_FORCE_IMMED_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT 24 ++#define DPI_DMA_CONTROL_FORCE_DRAIN_MASK BIT(DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT 25 ++#define DPI_DMA_CONTROL_FORCE_EMPTY_MASK BIT(DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT) ++ ++// IRQ_ENABLES ++#define DPI_DMA_IRQ_EN 0x04 ++#define DPI_DMA_IRQ_EN_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_EN_DMA_READY_MASK BIT(DPI_DMA_IRQ_EN_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_EN_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_EN_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_EN_FRAME_START_MASK BIT(DPI_DMA_IRQ_EN_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_EN_TE_SHIFT 4 ++#define DPI_DMA_IRQ_EN_TE_MASK BIT(DPI_DMA_IRQ_EN_TE_SHIFT) ++#define DPI_DMA_IRQ_EN_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_EN_ERROR_MASK BIT(DPI_DMA_IRQ_EN_ERROR_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_EN_MATCH_MASK BIT(DPI_DMA_IRQ_EN_MATCH_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT 16 ++#define DPI_DMA_IRQ_EN_MATCH_LINE_MASK (0xFFF << DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT) ++ ++// IRQ_FLAGS ++#define DPI_DMA_IRQ_FLAGS 0x08 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_MASK BIT(DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_MASK BIT(DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_TE_SHIFT 4 ++#define DPI_DMA_IRQ_FLAGS_TE_MASK BIT(DPI_DMA_IRQ_FLAGS_TE_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_FLAGS_ERROR_MASK BIT(DPI_DMA_IRQ_FLAGS_ERROR_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_FLAGS_MATCH_MASK BIT(DPI_DMA_IRQ_FLAGS_MATCH_SHIFT) ++ ++// QOS ++#define DPI_DMA_QOS 0xC ++#define DPI_DMA_QOS_DQOS_SHIFT 0 ++#define DPI_DMA_QOS_DQOS_MASK (0xF << DPI_DMA_QOS_DQOS_SHIFT) ++#define DPI_DMA_QOS_ULEV_SHIFT 4 ++#define DPI_DMA_QOS_ULEV_MASK (0xF << DPI_DMA_QOS_ULEV_SHIFT) ++#define DPI_DMA_QOS_UQOS_SHIFT 8 ++#define DPI_DMA_QOS_UQOS_MASK (0xF << DPI_DMA_QOS_UQOS_SHIFT) ++#define DPI_DMA_QOS_LLEV_SHIFT 12 ++#define DPI_DMA_QOS_LLEV_MASK (0xF << DPI_DMA_QOS_LLEV_SHIFT) ++#define DPI_DMA_QOS_LQOS_SHIFT 16 ++#define DPI_DMA_QOS_LQOS_MASK (0xF << DPI_DMA_QOS_LQOS_SHIFT) ++ ++// Panics ++#define DPI_DMA_PANICS 0x38 ++#define DPI_DMA_PANICS_UPPER_COUNT_SHIFT 0 ++#define DPI_DMA_PANICS_UPPER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_UPPER_COUNT_SHIFT) ++#define DPI_DMA_PANICS_LOWER_COUNT_SHIFT 16 ++#define DPI_DMA_PANICS_LOWER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_LOWER_COUNT_SHIFT) ++ ++// DMA Address Lower: ++#define DPI_DMA_DMA_ADDR_L 0x10 ++ ++// DMA Address Upper: ++#define DPI_DMA_DMA_ADDR_H 0x40 ++ ++// DMA stride ++#define DPI_DMA_DMA_STRIDE 0x14 ++ ++// Visible Area ++#define DPI_DMA_VISIBLE_AREA 0x18 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT 0 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT) ++#define DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT 16 ++#define DPI_DMA_VISIBLE_AREA_COLSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT) ++ ++// Sync width ++#define DPI_DMA_SYNC_WIDTH 0x1C ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT 0 ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT) ++#define DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT 16 ++#define DPI_DMA_SYNC_WIDTH_COLSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT) ++ ++// Back porch ++#define DPI_DMA_BACK_PORCH 0x20 ++#define DPI_DMA_BACK_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_BACK_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_BACK_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_BACK_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_COLSM1_SHIFT) ++ ++// Front porch ++#define DPI_DMA_FRONT_PORCH 0x24 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_FRONT_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_FRONT_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_COLSM1_SHIFT) ++ ++// Input masks ++#define DPI_DMA_IMASK 0x2C ++#define DPI_DMA_IMASK_R_SHIFT 0 ++#define DPI_DMA_IMASK_R_MASK (0x3FF << DPI_DMA_IMASK_R_SHIFT) ++#define DPI_DMA_IMASK_G_SHIFT 10 ++#define DPI_DMA_IMASK_G_MASK (0x3FF << DPI_DMA_IMASK_G_SHIFT) ++#define DPI_DMA_IMASK_B_SHIFT 20 ++#define DPI_DMA_IMASK_B_MASK (0x3FF << DPI_DMA_IMASK_B_SHIFT) ++ ++// Output Masks ++#define DPI_DMA_OMASK 0x30 ++#define DPI_DMA_OMASK_R_SHIFT 0 ++#define DPI_DMA_OMASK_R_MASK (0x3FF << DPI_DMA_OMASK_R_SHIFT) ++#define DPI_DMA_OMASK_G_SHIFT 10 ++#define DPI_DMA_OMASK_G_MASK (0x3FF << DPI_DMA_OMASK_G_SHIFT) ++#define DPI_DMA_OMASK_B_SHIFT 20 ++#define DPI_DMA_OMASK_B_MASK (0x3FF << DPI_DMA_OMASK_B_SHIFT) ++ ++// Shifts ++#define DPI_DMA_SHIFT 0x28 ++#define DPI_DMA_SHIFT_IR_SHIFT 0 ++#define DPI_DMA_SHIFT_IR_MASK (0x1F << DPI_DMA_SHIFT_IR_SHIFT) ++#define DPI_DMA_SHIFT_IG_SHIFT 5 ++#define DPI_DMA_SHIFT_IG_MASK (0x1F << DPI_DMA_SHIFT_IG_SHIFT) ++#define DPI_DMA_SHIFT_IB_SHIFT 10 ++#define DPI_DMA_SHIFT_IB_MASK (0x1F << DPI_DMA_SHIFT_IB_SHIFT) ++#define DPI_DMA_SHIFT_OR_SHIFT 15 ++#define DPI_DMA_SHIFT_OR_MASK (0x1F << DPI_DMA_SHIFT_OR_SHIFT) ++#define DPI_DMA_SHIFT_OG_SHIFT 20 ++#define DPI_DMA_SHIFT_OG_MASK (0x1F << DPI_DMA_SHIFT_OG_SHIFT) ++#define DPI_DMA_SHIFT_OB_SHIFT 25 ++#define DPI_DMA_SHIFT_OB_MASK (0x1F << DPI_DMA_SHIFT_OB_SHIFT) ++ ++// Scaling ++#define DPI_DMA_RGBSZ 0x34 ++#define DPI_DMA_RGBSZ_BPP_SHIFT 16 ++#define DPI_DMA_RGBSZ_BPP_MASK (0x3 << DPI_DMA_RGBSZ_BPP_SHIFT) ++#define DPI_DMA_RGBSZ_R_SHIFT 0 ++#define DPI_DMA_RGBSZ_R_MASK (0xF << DPI_DMA_RGBSZ_R_SHIFT) ++#define DPI_DMA_RGBSZ_G_SHIFT 4 ++#define DPI_DMA_RGBSZ_G_MASK (0xF << DPI_DMA_RGBSZ_G_SHIFT) ++#define DPI_DMA_RGBSZ_B_SHIFT 8 ++#define DPI_DMA_RGBSZ_B_MASK (0xF << DPI_DMA_RGBSZ_B_SHIFT) ++ ++// Status ++#define DPI_DMA_STATUS 0x3c ++ ++#define BITS(field, val) (((val) << (field ## _SHIFT)) & (field ## _MASK)) ++ ++static unsigned int rp1dpi_hw_read(struct rp1_dpi *dpi, unsigned int reg) ++{ ++ void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg; ++ ++ return readl(addr); ++} ++ ++static void rp1dpi_hw_write(struct rp1_dpi *dpi, unsigned int reg, unsigned int val) ++{ ++ void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg; ++ ++ writel(val, addr); ++} ++ ++int rp1dpi_hw_busy(struct rp1_dpi *dpi) ++{ ++ return (rp1dpi_hw_read(dpi, DPI_DMA_STATUS) & 0xF8F) ? 1 : 0; ++} ++ ++/* Table of supported input (in-memory/DMA) pixel formats. */ ++struct rp1dpi_ipixfmt { ++ u32 format; /* DRM format code */ ++ u32 mask; /* RGB masks (10 bits each, left justified) */ ++ u32 shift; /* RGB MSB positions in the memory word */ ++ u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */ ++}; ++ ++#define IMASK_RGB(r, g, b) (BITS(DPI_DMA_IMASK_R, r) | \ ++ BITS(DPI_DMA_IMASK_G, g) | \ ++ BITS(DPI_DMA_IMASK_B, b)) ++#define OMASK_RGB(r, g, b) (BITS(DPI_DMA_OMASK_R, r) | \ ++ BITS(DPI_DMA_OMASK_G, g) | \ ++ BITS(DPI_DMA_OMASK_B, b)) ++#define ISHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_IR, r) | \ ++ BITS(DPI_DMA_SHIFT_IG, g) | \ ++ BITS(DPI_DMA_SHIFT_IB, b)) ++#define OSHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_OR, r) | \ ++ BITS(DPI_DMA_SHIFT_OG, g) | \ ++ BITS(DPI_DMA_SHIFT_OB, b)) ++ ++static const struct rp1dpi_ipixfmt my_formats[] = { ++ { ++ .format = DRM_FORMAT_XRGB8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_XBGR8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_RGB888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_BGR888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_RGB565, ++ .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = ISHIFT_RGB(15, 10, 4), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) | ++ BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1), ++ }, ++ { ++ .format = DRM_FORMAT_BGR565, ++ .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = ISHIFT_RGB(4, 10, 15), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) | ++ BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1), ++ } ++}; ++ ++static u32 set_output_format(u32 bus_format, u32 *shift, u32 *imask, u32 *rgbsz) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB565_1X16: ++ if (*shift == ISHIFT_RGB(15, 10, 4)) { ++ /* When framebuffer is RGB565, we can output RGB565 */ ++ *shift = ISHIFT_RGB(15, 7, 0) | OSHIFT_RGB(19, 9, 0); ++ *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK; ++ return OMASK_RGB(0x3fc, 0x3fc, 0); ++ } ++ ++ /* due to a HW limitation, bit-depth is effectively RGB535 */ ++ *shift |= OSHIFT_RGB(19, 14, 6); ++ *imask &= IMASK_RGB(0x3e0, 0x380, 0x3e0); ++ *rgbsz = BITS(DPI_DMA_RGBSZ_G, 5) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK); ++ return OMASK_RGB(0x3e0, 0x39c, 0x3e0); ++ ++ case MEDIA_BUS_FMT_RGB666_1X18: ++ case MEDIA_BUS_FMT_BGR666_1X18: ++ /* due to a HW limitation, bit-depth is effectively RGB444 */ ++ *shift |= OSHIFT_RGB(23, 15, 7); ++ *imask &= IMASK_RGB(0x3c0, 0x3c0, 0x3c0); ++ *rgbsz = BITS(DPI_DMA_RGBSZ_R, 2) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK); ++ return OMASK_RGB(0x330, 0x3c0, 0x3c0); ++ ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_BGR888_1X24: ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ /* The full 24 bits can be output. Note that RP1's internal wiring means ++ * that 8.8.8 to GPIO pads can share with 10.10.10 to the onboard VDAC. ++ */ ++ *shift |= OSHIFT_RGB(29, 19, 9); ++ return OMASK_RGB(0x3fc, 0x3fc, 0x3fc); ++ ++ default: ++ /* RGB666_1x24_CPADHI, BGR666_1X24_CPADHI and "RGB565_666" formats */ ++ *shift |= OSHIFT_RGB(27, 17, 7); ++ *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK; ++ return OMASK_RGB(0x3f0, 0x3f0, 0x3f0); ++ } ++} ++ ++#define BUS_FMT_IS_BGR(fmt) ( \ ++ ((fmt) == MEDIA_BUS_FMT_BGR666_1X18) || \ ++ ((fmt) == MEDIA_BUS_FMT_BGR666_1X24_CPADHI) || \ ++ ((fmt) == MEDIA_BUS_FMT_BGR888_1X24)) ++ ++void rp1dpi_hw_setup(struct rp1_dpi *dpi, ++ u32 in_format, u32 bus_format, bool de_inv, ++ struct drm_display_mode const *mode) ++{ ++ u32 shift, imask, omask, rgbsz; ++ int i; ++ ++ pr_info("%s: in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d %dkHz %cH%cV%cD%cC", ++ __func__, in_format, in_format >> 8, in_format >> 16, in_format >> 24, bus_format, ++ mode->hdisplay, mode->vdisplay, ++ mode->htotal, mode->vtotal, ++ mode->clock, ++ (mode->flags & DRM_MODE_FLAG_NHSYNC) ? '-' : '+', ++ (mode->flags & DRM_MODE_FLAG_NVSYNC) ? '-' : '+', ++ de_inv ? '-' : '+', ++ dpi->clk_inv ? '-' : '+'); ++ ++ /* ++ * Configure all DPI/DMA block registers, except base address. ++ * DMA will not actually start until a FB base address is specified ++ * using rp1dpi_hw_update(). ++ */ ++ rp1dpi_hw_write(dpi, DPI_DMA_VISIBLE_AREA, ++ BITS(DPI_DMA_VISIBLE_AREA_ROWSM1, mode->vdisplay - 1) | ++ BITS(DPI_DMA_VISIBLE_AREA_COLSM1, mode->hdisplay - 1)); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_SYNC_WIDTH, ++ BITS(DPI_DMA_SYNC_WIDTH_ROWSM1, mode->vsync_end - mode->vsync_start - 1) | ++ BITS(DPI_DMA_SYNC_WIDTH_COLSM1, mode->hsync_end - mode->hsync_start - 1)); ++ ++ /* In these registers, "back porch" time includes sync width */ ++ rp1dpi_hw_write(dpi, DPI_DMA_BACK_PORCH, ++ BITS(DPI_DMA_BACK_PORCH_ROWSM1, mode->vtotal - mode->vsync_start - 1) | ++ BITS(DPI_DMA_BACK_PORCH_COLSM1, mode->htotal - mode->hsync_start - 1)); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_FRONT_PORCH, ++ BITS(DPI_DMA_FRONT_PORCH_ROWSM1, mode->vsync_start - mode->vdisplay - 1) | ++ BITS(DPI_DMA_FRONT_PORCH_COLSM1, mode->hsync_start - mode->hdisplay - 1)); ++ ++ /* Input to output pixel format conversion */ ++ for (i = 0; i < ARRAY_SIZE(my_formats); ++i) { ++ if (my_formats[i].format == in_format) ++ break; ++ } ++ if (i >= ARRAY_SIZE(my_formats)) { ++ pr_err("%s: bad input format\n", __func__); ++ i = 4; ++ } ++ if (BUS_FMT_IS_BGR(bus_format)) ++ i ^= 1; ++ shift = my_formats[i].shift; ++ imask = my_formats[i].mask; ++ rgbsz = my_formats[i].rgbsz; ++ omask = set_output_format(bus_format, &shift, &imask, &rgbsz); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_IMASK, imask); ++ rp1dpi_hw_write(dpi, DPI_DMA_OMASK, omask); ++ rp1dpi_hw_write(dpi, DPI_DMA_SHIFT, shift); ++ rp1dpi_hw_write(dpi, DPI_DMA_RGBSZ, rgbsz); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_QOS, ++ BITS(DPI_DMA_QOS_DQOS, 0x0) | ++ BITS(DPI_DMA_QOS_ULEV, 0xb) | ++ BITS(DPI_DMA_QOS_UQOS, 0x2) | ++ BITS(DPI_DMA_QOS_LLEV, 0x8) | ++ BITS(DPI_DMA_QOS_LQOS, 0x7)); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, -1); ++ rp1dpi_hw_vblank_ctrl(dpi, 1); ++ ++ i = rp1dpi_hw_busy(dpi); ++ if (i) ++ pr_warn("%s: Unexpectedly busy at start!", __func__); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_CONTROL, ++ BITS(DPI_DMA_CONTROL_ARM, !i) | ++ BITS(DPI_DMA_CONTROL_AUTO_REPEAT, 1) | ++ BITS(DPI_DMA_CONTROL_HIGH_WATER, 448) | ++ BITS(DPI_DMA_CONTROL_DEN_POL, de_inv) | ++ BITS(DPI_DMA_CONTROL_HSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NHSYNC)) | ++ BITS(DPI_DMA_CONTROL_VSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NVSYNC)) | ++ BITS(DPI_DMA_CONTROL_COLORM, 0) | ++ BITS(DPI_DMA_CONTROL_SHUTDN, 0) | ++ BITS(DPI_DMA_CONTROL_HBP_EN, (mode->htotal != mode->hsync_end)) | ++ BITS(DPI_DMA_CONTROL_HFP_EN, (mode->hsync_start != mode->hdisplay)) | ++ BITS(DPI_DMA_CONTROL_VBP_EN, (mode->vtotal != mode->vsync_end)) | ++ BITS(DPI_DMA_CONTROL_VFP_EN, (mode->vsync_start != mode->vdisplay)) | ++ BITS(DPI_DMA_CONTROL_HSYNC_EN, (mode->hsync_end != mode->hsync_start)) | ++ BITS(DPI_DMA_CONTROL_VSYNC_EN, (mode->vsync_end != mode->vsync_start))); ++} ++ ++void rp1dpi_hw_update(struct rp1_dpi *dpi, dma_addr_t addr, u32 offset, u32 stride) ++{ ++ u64 a = addr + offset; ++ ++ /* ++ * Update STRIDE, DMAH and DMAL only. When called after rp1dpi_hw_setup(), ++ * DMA starts immediately; if already running, the buffer will flip at ++ * the next vertical sync event. ++ */ ++ rp1dpi_hw_write(dpi, DPI_DMA_DMA_STRIDE, stride); ++ rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_H, a >> 32); ++ rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_L, a & 0xFFFFFFFFu); ++} ++ ++void rp1dpi_hw_stop(struct rp1_dpi *dpi) ++{ ++ u32 ctrl; ++ ++ /* ++ * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for ++ * the current and any queued frame to end. "Force drain" flags are not used, ++ * as they seem to prevent DMA from re-starting properly; it's safer to wait. ++ */ ++ reinit_completion(&dpi->finished); ++ ctrl = rp1dpi_hw_read(dpi, DPI_DMA_CONTROL); ++ ctrl &= ~(DPI_DMA_CONTROL_ARM_MASK | DPI_DMA_CONTROL_AUTO_REPEAT_MASK); ++ rp1dpi_hw_write(dpi, DPI_DMA_CONTROL, ctrl); ++ if (!wait_for_completion_timeout(&dpi->finished, HZ / 10)) ++ drm_err(dpi->drm, "%s: timed out waiting for idle\n", __func__); ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN, 0); ++} ++ ++void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable) ++{ ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN, ++ BITS(DPI_DMA_IRQ_EN_AFIFO_EMPTY, 1) | ++ BITS(DPI_DMA_IRQ_EN_UNDERFLOW, 1) | ++ BITS(DPI_DMA_IRQ_EN_DMA_READY, !!enable) | ++ BITS(DPI_DMA_IRQ_EN_MATCH_LINE, 4095)); ++} ++ ++irqreturn_t rp1dpi_hw_isr(int irq, void *dev) ++{ ++ struct rp1_dpi *dpi = dev; ++ u32 u = rp1dpi_hw_read(dpi, DPI_DMA_IRQ_FLAGS); ++ ++ if (u) { ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, u); ++ if (dpi) { ++ if (u & DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK) ++ drm_err_ratelimited(dpi->drm, ++ "Underflow! (panics=0x%08x)\n", ++ rp1dpi_hw_read(dpi, DPI_DMA_PANICS)); ++ if (u & DPI_DMA_IRQ_FLAGS_DMA_READY_MASK) ++ drm_crtc_handle_vblank(&dpi->pipe.crtc); ++ if (u & DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK) ++ complete(&dpi->finished); ++ } ++ } ++ return u ? IRQ_HANDLED : IRQ_NONE; ++} diff --git a/target/linux/bcm27xx/patches-6.1/950-0887-drm-Add-RP1-VEC-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0887-drm-Add-RP1-VEC-driver.patch new file mode 100644 index 0000000000..5bf657ab24 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0887-drm-Add-RP1-VEC-driver.patch @@ -0,0 +1,3078 @@ +From 09c2c6aad0fed44182defecd274579770feb0ae2 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Tue, 19 Sep 2023 17:54:41 +0100 +Subject: [PATCH] drm: Add RP1 VEC driver + +Add support for the RP1 VEC hardware. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/rp1/rp1-vec/Kconfig | 12 + + drivers/gpu/drm/rp1/rp1-vec/Makefile | 5 + + drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c | 539 ++++++++ + drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h | 79 ++ + drivers/gpu/drm/rp1/rp1-vec/rp1_vec_cfg.c | 508 ++++++++ + drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c | 469 +++++++ + drivers/gpu/drm/rp1/rp1-vec/vec_regs.h | 1420 +++++++++++++++++++++ + 7 files changed, 3032 insertions(+) + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/Kconfig + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec_cfg.c + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/vec_regs.h + +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/Kconfig +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config DRM_RP1_VEC ++ tristate "DRM Support for RP1 VEC" ++ depends on DRM ++ select MFD_RP1 ++ select DRM_GEM_DMA_HELPER ++ select DRM_KMS_HELPER ++ select DRM_VRAM_HELPER ++ select DRM_TTM ++ select DRM_TTM_HELPER ++ help ++ Choose this option to enable Video Out on RP1 +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++drm-rp1-vec-y := rp1_vec.o rp1_vec_hw.o rp1_vec_cfg.o ++ ++obj-$(CONFIG_DRM_RP1_VEC) += drm-rp1-vec.o +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c +@@ -0,0 +1,539 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for VEC output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_vec.h" ++ ++/* ++ * Default TV standard parameter; it may be overridden by the OF ++ * property "tv_norm" (which should be one of the strings below). ++ * ++ * The default (empty string) supports various 60Hz and 50Hz modes, ++ * and will automatically select NTSC[-M] or PAL[-BDGHIKL]; the two ++ * "fake" 60Hz standards NTSC-443 and PAL60 also support 50Hz PAL. ++ * Other values will restrict the set of video modes offered. ++ * ++ * Finally, the DRM connector property "mode" (which is an integer) ++ * can be used to override this value, but it does not prevent the ++ * selection of an inapplicable video mode. ++ */ ++ ++static char *rp1vec_tv_norm_str; ++module_param_named(tv_norm, rp1vec_tv_norm_str, charp, 0600); ++MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" ++ "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n" ++ "\t\t\tPAL60.\n" ++ "\t\tDefault: empty string: infer PAL for a 50 Hz mode,\n" ++ "\t\t\tNTSC otherwise"); ++ ++const char * const rp1vec_tvstd_names[] = { ++ [RP1VEC_TVSTD_NTSC] = "NTSC", ++ [RP1VEC_TVSTD_NTSC_J] = "NTSC-J", ++ [RP1VEC_TVSTD_NTSC_443] = "NTSC-443", ++ [RP1VEC_TVSTD_PAL] = "PAL", ++ [RP1VEC_TVSTD_PAL_M] = "PAL-M", ++ [RP1VEC_TVSTD_PAL_N] = "PAL-N", ++ [RP1VEC_TVSTD_PAL60] = "PAL60", ++ [RP1VEC_TVSTD_DEFAULT] = "", ++}; ++ ++static int rp1vec_parse_tv_norm(const char *str) ++{ ++ int i; ++ ++ if (str && *str) { ++ for (i = 0; i < ARRAY_SIZE(rp1vec_tvstd_names); ++i) { ++ if (strcasecmp(str, rp1vec_tvstd_names[i]) == 0) ++ return i; ++ } ++ } ++ return RP1VEC_TVSTD_DEFAULT; ++} ++ ++static void rp1vec_pipe_update(struct drm_simple_display_pipe *pipe, ++ struct drm_plane_state *old_state) ++{ ++ struct drm_pending_vblank_event *event; ++ unsigned long flags; ++ struct drm_framebuffer *fb = pipe->plane.state->fb; ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ struct drm_gem_object *gem = fb ? drm_gem_fb_get_obj(fb, 0) : NULL; ++ struct drm_gem_dma_object *dma_obj = gem ? to_drm_gem_dma_obj(gem) : NULL; ++ bool can_update = fb && dma_obj && vec && vec->pipe_enabled; ++ ++ /* (Re-)start VEC where required; and update FB address */ ++ if (can_update) { ++ if (!vec->vec_running || fb->format->format != vec->cur_fmt) { ++ if (vec->vec_running && fb->format->format != vec->cur_fmt) { ++ rp1vec_hw_stop(vec); ++ vec->vec_running = false; ++ } ++ if (!vec->vec_running) { ++ rp1vec_hw_setup(vec, ++ fb->format->format, ++ &pipe->crtc.state->mode, ++ vec->connector.state->tv.mode); ++ vec->vec_running = true; ++ } ++ vec->cur_fmt = fb->format->format; ++ drm_crtc_vblank_on(&pipe->crtc); ++ } ++ rp1vec_hw_update(vec, dma_obj->dma_addr, fb->offsets[0], fb->pitches[0]); ++ } ++ ++ /* Check if VBLANK callback needs to be armed (or sent immediately in some error cases). ++ * Note there is a tiny probability of a race between rp1vec_dma_update() and IRQ; ++ * ordering it this way around is safe, but theoretically might delay an extra frame. ++ */ ++ spin_lock_irqsave(&pipe->crtc.dev->event_lock, flags); ++ event = pipe->crtc.state->event; ++ if (event) { ++ pipe->crtc.state->event = NULL; ++ if (can_update && drm_crtc_vblank_get(&pipe->crtc) == 0) ++ drm_crtc_arm_vblank_event(&pipe->crtc, event); ++ else ++ drm_crtc_send_vblank_event(&pipe->crtc, event); ++ } ++ spin_unlock_irqrestore(&pipe->crtc.dev->event_lock, flags); ++} ++ ++static void rp1vec_pipe_enable(struct drm_simple_display_pipe *pipe, ++ struct drm_crtc_state *crtc_state, ++ struct drm_plane_state *plane_state) ++{ ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ dev_info(&vec->pdev->dev, __func__); ++ vec->pipe_enabled = true; ++ vec->cur_fmt = 0xdeadbeef; ++ rp1vec_vidout_setup(vec); ++ rp1vec_pipe_update(pipe, 0); ++} ++ ++static void rp1vec_pipe_disable(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ dev_info(&vec->pdev->dev, __func__); ++ drm_crtc_vblank_off(&pipe->crtc); ++ if (vec) { ++ if (vec->vec_running) { ++ rp1vec_hw_stop(vec); ++ vec->vec_running = false; ++ } ++ vec->pipe_enabled = false; ++ } ++} ++ ++static int rp1vec_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ if (pipe && pipe->crtc.dev) { ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ if (vec) ++ rp1vec_hw_vblank_ctrl(vec, 1); ++ } ++ return 0; ++} ++ ++static void rp1vec_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ if (pipe && pipe->crtc.dev) { ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ if (vec) ++ rp1vec_hw_vblank_ctrl(vec, 0); ++ } ++} ++ ++static const struct drm_simple_display_pipe_funcs rp1vec_pipe_funcs = { ++ .enable = rp1vec_pipe_enable, ++ .update = rp1vec_pipe_update, ++ .disable = rp1vec_pipe_disable, ++ .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, ++ .enable_vblank = rp1vec_pipe_enable_vblank, ++ .disable_vblank = rp1vec_pipe_disable_vblank, ++}; ++ ++static void rp1vec_connector_destroy(struct drm_connector *connector) ++{ ++ drm_connector_unregister(connector); ++ drm_connector_cleanup(connector); ++} ++ ++static const struct drm_display_mode rp1vec_modes[4] = { ++ { /* Full size 525/60i with Rec.601 pixel rate */ ++ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 14, 720 + 14 + 64, 858, 0, ++ 480, 480 + 7, 480 + 7 + 6, 525, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ }, ++ { /* Cropped and horizontally squashed to be TV-safe */ ++ DRM_MODE("704x432i", DRM_MODE_TYPE_DRIVER, 15429, ++ 704, 704 + 72, 704 + 72 + 72, 980, 0, ++ 432, 432 + 31, 432 + 31 + 6, 525, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ }, ++ { /* Full size 625/50i with Rec.601 pixel rate */ ++ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 20, 720 + 20 + 64, 864, 0, ++ 576, 576 + 4, 576 + 4 + 6, 625, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ }, ++ { /* Cropped and squashed, for square(ish) pixels */ ++ DRM_MODE("704x512i", DRM_MODE_TYPE_DRIVER, 15429, ++ 704, 704 + 80, 704 + 80 + 72, 987, 0, ++ 512, 512 + 36, 512 + 36 + 6, 625, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ } ++}; ++ ++static int rp1vec_connector_get_modes(struct drm_connector *connector) ++{ ++ struct rp1_vec *vec = container_of(connector, struct rp1_vec, connector); ++ bool ok525 = RP1VEC_TVSTD_SUPPORT_525(vec->tv_norm); ++ bool ok625 = RP1VEC_TVSTD_SUPPORT_625(vec->tv_norm); ++ int i, prog, n = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(rp1vec_modes); i++) { ++ if ((rp1vec_modes[i].vtotal == 625) ? ok625 : ok525) { ++ for (prog = 0; prog < 2; prog++) { ++ struct drm_display_mode *mode = ++ drm_mode_duplicate(connector->dev, ++ &rp1vec_modes[i]); ++ ++ if (prog) { ++ mode->flags &= ~DRM_MODE_FLAG_INTERLACE; ++ mode->vdisplay >>= 1; ++ mode->vsync_start >>= 1; ++ mode->vsync_end >>= 1; ++ mode->vtotal >>= 1; ++ } ++ ++ if (mode->hdisplay == 704 && ++ mode->vtotal == ((ok525) ? 525 : 625)) ++ mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ drm_mode_set_name(mode); ++ drm_mode_probed_add(connector, mode); ++ n++; ++ } ++ } ++ } ++ ++ return n; ++} ++ ++static void rp1vec_connector_reset(struct drm_connector *connector) ++{ ++ struct rp1_vec *vec = container_of(connector, struct rp1_vec, connector); ++ ++ drm_atomic_helper_connector_reset(connector); ++ if (connector->state) ++ connector->state->tv.mode = vec->tv_norm; ++} ++ ++static int rp1vec_connector_atomic_check(struct drm_connector *conn, ++ struct drm_atomic_state *state) ++{ struct drm_connector_state *old_state = ++ drm_atomic_get_old_connector_state(state, conn); ++ struct drm_connector_state *new_state = ++ drm_atomic_get_new_connector_state(state, conn); ++ ++ if (new_state->crtc && old_state->tv.mode != new_state->tv.mode) { ++ struct drm_crtc_state *crtc_state = ++ drm_atomic_get_new_crtc_state(state, new_state->crtc); ++ ++ crtc_state->mode_changed = true; ++ } ++ ++ return 0; ++} ++ ++static enum drm_mode_status rp1vec_mode_valid(struct drm_device *dev, ++ const struct drm_display_mode *mode) ++{ ++ /* ++ * Check the mode roughly matches one of our standard modes ++ * (optionally half-height and progressive). Ignore H/V sync ++ * timings which for interlaced TV are approximate at best. ++ */ ++ int i, prog; ++ ++ prog = !(mode->flags & DRM_MODE_FLAG_INTERLACE); ++ ++ for (i = 0; i < ARRAY_SIZE(rp1vec_modes); i++) { ++ const struct drm_display_mode *ref = rp1vec_modes + i; ++ ++ if (mode->hdisplay == ref->hdisplay && ++ mode->vdisplay == (ref->vdisplay >> prog) && ++ mode->clock + 2 >= ref->clock && ++ mode->clock <= ref->clock + 2 && ++ mode->htotal + 2 >= ref->htotal && ++ mode->htotal <= ref->htotal + 2 && ++ mode->vtotal + 2 >= (ref->vtotal >> prog) && ++ mode->vtotal <= (ref->vtotal >> prog) + 2) ++ return MODE_OK; ++ } ++ return MODE_BAD; ++} ++ ++static const struct drm_connector_helper_funcs rp1vec_connector_helper_funcs = { ++ .get_modes = rp1vec_connector_get_modes, ++ .atomic_check = rp1vec_connector_atomic_check, ++}; ++ ++static const struct drm_connector_funcs rp1vec_connector_funcs = { ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = rp1vec_connector_destroy, ++ .reset = rp1vec_connector_reset, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static const struct drm_mode_config_funcs rp1vec_mode_funcs = { ++ .fb_create = drm_gem_fb_create, ++ .atomic_check = drm_atomic_helper_check, ++ .atomic_commit = drm_atomic_helper_commit, ++ .mode_valid = rp1vec_mode_valid, ++}; ++ ++static const u32 rp1vec_formats[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565 ++}; ++ ++static void rp1vec_stopall(struct drm_device *drm) ++{ ++ if (drm->dev_private) { ++ struct rp1_vec *vec = drm->dev_private; ++ ++ if (vec->vec_running || rp1vec_hw_busy(vec)) { ++ rp1vec_hw_stop(vec); ++ vec->vec_running = false; ++ } ++ rp1vec_vidout_poweroff(vec); ++ } ++} ++ ++DEFINE_DRM_GEM_DMA_FOPS(rp1vec_fops); ++ ++static struct drm_driver rp1vec_driver = { ++ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, ++ .fops = &rp1vec_fops, ++ .name = "drm-rp1-vec", ++ .desc = "drm-rp1-vec", ++ .date = "0", ++ .major = 1, ++ .minor = 0, ++ DRM_GEM_DMA_DRIVER_OPS, ++ .release = rp1vec_stopall, ++}; ++ ++static int rp1vec_platform_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct drm_device *drm; ++ struct rp1_vec *vec; ++ const char *str; ++ int i, ret; ++ ++ dev_info(dev, __func__); ++ drm = drm_dev_alloc(&rp1vec_driver, dev); ++ if (IS_ERR(drm)) { ++ ret = PTR_ERR(drm); ++ dev_err(dev, "%s drm_dev_alloc %d", __func__, ret); ++ return ret; ++ } ++ ++ vec = drmm_kzalloc(drm, sizeof(*vec), GFP_KERNEL); ++ if (!vec) { ++ dev_err(dev, "%s drmm_kzalloc failed", __func__); ++ ret = -ENOMEM; ++ goto err_free_drm; ++ } ++ init_completion(&vec->finished); ++ vec->drm = drm; ++ vec->pdev = pdev; ++ drm->dev_private = vec; ++ platform_set_drvdata(pdev, drm); ++ ++ str = rp1vec_tv_norm_str; ++ of_property_read_string(dev->of_node, "tv_norm", &str); ++ vec->tv_norm = rp1vec_parse_tv_norm(str); ++ ++ for (i = 0; i < RP1VEC_NUM_HW_BLOCKS; i++) { ++ vec->hw_base[i] = ++ devm_ioremap_resource(dev, ++ platform_get_resource(vec->pdev, IORESOURCE_MEM, i)); ++ if (IS_ERR(vec->hw_base[i])) { ++ ret = PTR_ERR(vec->hw_base[i]); ++ dev_err(dev, "Error memory mapping regs[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ret = platform_get_irq(vec->pdev, 0); ++ if (ret > 0) ++ ret = devm_request_irq(dev, ret, rp1vec_hw_isr, ++ IRQF_SHARED, "rp1-vec", vec); ++ if (ret) { ++ dev_err(dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_free_drm; ++ } ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); ++ ++ vec->vec_clock = devm_clk_get(dev, NULL); ++ if (IS_ERR(vec->vec_clock)) { ++ ret = PTR_ERR(vec->vec_clock); ++ goto err_free_drm; ++ } ++ ret = clk_prepare_enable(vec->vec_clock); ++ ++ ret = drmm_mode_config_init(drm); ++ if (ret) ++ goto err_free_drm; ++ drm->mode_config.max_width = 768; ++ drm->mode_config.max_height = 576; ++ drm->mode_config.fb_base = 0; ++ drm->mode_config.preferred_depth = 32; ++ drm->mode_config.prefer_shadow = 0; ++ drm->mode_config.prefer_shadow_fbdev = 1; ++ //drm->mode_config.fbdev_use_iomem = false; ++ drm->mode_config.quirk_addfb_prefer_host_byte_order = true; ++ drm->mode_config.funcs = &rp1vec_mode_funcs; ++ drm_vblank_init(drm, 1); ++ ++ ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(rp1vec_tvstd_names), ++ rp1vec_tvstd_names); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_connector_init(drm, &vec->connector, &rp1vec_connector_funcs, ++ DRM_MODE_CONNECTOR_Composite); ++ if (ret) ++ goto err_free_drm; ++ ++ vec->connector.interlace_allowed = true; ++ drm_connector_helper_add(&vec->connector, &rp1vec_connector_helper_funcs); ++ ++ drm_object_attach_property(&vec->connector.base, ++ drm->mode_config.tv_mode_property, ++ vec->tv_norm); ++ ++ ret = drm_simple_display_pipe_init(drm, ++ &vec->pipe, ++ &rp1vec_pipe_funcs, ++ rp1vec_formats, ++ ARRAY_SIZE(rp1vec_formats), ++ NULL, ++ &vec->connector); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_mode_config_reset(drm); ++ ++ ret = drm_dev_register(drm, 0); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_fbdev_generic_setup(drm, 32); /* the "32" is preferred BPP */ ++ return ret; ++ ++err_free_drm: ++ dev_info(dev, "%s fail %d", __func__, ret); ++ drm_dev_put(drm); ++ return ret; ++} ++ ++static int rp1vec_platform_remove(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1vec_stopall(drm); ++ drm_dev_unregister(drm); ++ drm_atomic_helper_shutdown(drm); ++ drm_dev_put(drm); ++ ++ return 0; ++} ++ ++static void rp1vec_platform_shutdown(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1vec_stopall(drm); ++} ++ ++static const struct of_device_id rp1vec_of_match[] = { ++ { ++ .compatible = "raspberrypi,rp1vec", ++ }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rp1vec_of_match); ++ ++static struct platform_driver rp1vec_platform_driver = { ++ .probe = rp1vec_platform_probe, ++ .remove = rp1vec_platform_remove, ++ .shutdown = rp1vec_platform_shutdown, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rp1vec_of_match, ++ }, ++}; ++ ++module_platform_driver(rp1vec_platform_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("DRM driver for Composite Video on Raspberry Pi RP1"); ++MODULE_AUTHOR("Nick Hollinghurst"); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h +@@ -0,0 +1,79 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "drm-rp1-vec" ++#define DRIVER_NAME "drm-rp1-vec" ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define RP1VEC_HW_BLOCK_VEC 0 ++#define RP1VEC_HW_BLOCK_CFG 1 ++#define RP1VEC_NUM_HW_BLOCKS 2 ++ ++enum { ++ RP1VEC_TVSTD_NTSC = 0, /* +525 => NTSC 625 => PAL */ ++ RP1VEC_TVSTD_NTSC_J, /* +525 => NTSC-J 625 => PAL */ ++ RP1VEC_TVSTD_NTSC_443, /* +525 => NTSC-443 +625 => PAL */ ++ RP1VEC_TVSTD_PAL, /* 525 => NTSC +625 => PAL */ ++ RP1VEC_TVSTD_PAL_M, /* +525 => PAL-M 625 => PAL */ ++ RP1VEC_TVSTD_PAL_N, /* 525 => NTSC +625 => PAL-N */ ++ RP1VEC_TVSTD_PAL60, /* +525 => PAL60 +625 => PAL */ ++ RP1VEC_TVSTD_DEFAULT, /* +525 => NTSC +625 => PAL */ ++}; ++ ++/* Which standards support which modes? Those marked with + above */ ++#define RP1VEC_TVSTD_SUPPORT_525(n) ((0xD7 >> (n)) & 1) ++#define RP1VEC_TVSTD_SUPPORT_625(n) ((0xEC >> (n)) & 1) ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct rp1_vec { ++ /* DRM and platform device pointers */ ++ struct drm_device *drm; ++ struct platform_device *pdev; ++ ++ /* Framework and helper objects */ ++ struct drm_simple_display_pipe pipe; ++ struct drm_connector connector; ++ ++ /* Clock. We assume this is always at 108 MHz. */ ++ struct clk *vec_clock; ++ ++ /* Block (VCC, CFG) base addresses, and current state */ ++ void __iomem *hw_base[RP1VEC_NUM_HW_BLOCKS]; ++ u32 cur_fmt; ++ int tv_norm; ++ bool vec_running, pipe_enabled; ++ struct completion finished; ++}; ++ ++extern const char * const rp1vec_tvstd_names[]; ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the VEC/DMA block */ ++ ++void rp1vec_hw_setup(struct rp1_vec *vec, ++ u32 in_format, ++ struct drm_display_mode const *mode, ++ int tvstd); ++void rp1vec_hw_update(struct rp1_vec *vec, dma_addr_t addr, u32 offset, u32 stride); ++void rp1vec_hw_stop(struct rp1_vec *vec); ++int rp1vec_hw_busy(struct rp1_vec *vec); ++irqreturn_t rp1vec_hw_isr(int irq, void *dev); ++void rp1vec_hw_vblank_ctrl(struct rp1_vec *vec, int enable); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the VIDEO OUT CFG block and check RP1 platform */ ++ ++void rp1vec_vidout_setup(struct rp1_vec *vec); ++void rp1vec_vidout_poweroff(struct rp1_vec *vec); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_cfg.c +@@ -0,0 +1,508 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_vec.h" ++ ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_SEL ++// JTAG access : synchronous ++// Description : Selects source: VEC or DPI ++#define VIDEO_OUT_CFG_SEL_OFFSET 0x00000000 ++#define VIDEO_OUT_CFG_SEL_BITS 0x00000013 ++#define VIDEO_OUT_CFG_SEL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PCLK_INV ++// Description : Select dpi_pclk output port polarity inversion. ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_BITS 0x00000010 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_MSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_LSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PAD_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_BITS 0x00000002 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_MSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_LSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_VDAC_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_BITS 0x00000001 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_MSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_LSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_CFG ++// JTAG access : synchronous ++// Description : Configure SNPS VDAC ++#define VIDEO_OUT_CFG_VDAC_CFG_OFFSET 0x00000004 ++#define VIDEO_OUT_CFG_VDAC_CFG_BITS 0x1fffffff ++#define VIDEO_OUT_CFG_VDAC_CFG_RESET 0x0003ffff ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENCTR ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_BITS 0x1c000000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_MSB 28 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_LSB 26 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENSC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_BITS 0x03800000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_MSB 25 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_LSB 23 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENDAC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_BITS 0x00700000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_MSB 22 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_LSB 20 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENVBG ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_BITS 0x00080000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_MSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_LSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_BITS 0x00040000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_MSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_LSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC2GC ++// Description : dac2 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_BITS 0x0003f000 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_MSB 17 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_LSB 12 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC1GC ++// Description : dac1 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_BITS 0x00000fc0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_MSB 11 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_LSB 6 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC0GC ++// Description : dac0 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_BITS 0x0000003f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_MSB 5 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_STATUS ++// JTAG access : synchronous ++// Description : Read VDAC status ++#define VIDEO_OUT_CFG_VDAC_STATUS_OFFSET 0x00000008 ++#define VIDEO_OUT_CFG_VDAC_STATUS_BITS 0x00000017 ++#define VIDEO_OUT_CFG_VDAC_STATUS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3 ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_BITS 0x00000010 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_MSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_LSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_RESET "-" ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_BITS 0x00000007 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_MSB 2 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_MEM_PD ++// JTAG access : synchronous ++// Description : Control memory power down ++#define VIDEO_OUT_CFG_MEM_PD_OFFSET 0x0000000c ++#define VIDEO_OUT_CFG_MEM_PD_BITS 0x00000003 ++#define VIDEO_OUT_CFG_MEM_PD_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_VEC ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_BITS 0x00000002 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_MSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_LSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_DPI ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_BITS 0x00000001 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_MSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_LSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_TEST_OVERRIDE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_OFFSET 0x00000010 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_BITS 0xffffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_PAD ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_BITS 0x80000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_MSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_LSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS 0x40000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_MSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_LSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_RESET 0x00000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_BITS 0x3fffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_MSB 29 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_LSB 0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTR ++// JTAG access : synchronous ++// Description : Raw Interrupts ++#define VIDEO_OUT_CFG_INTR_OFFSET 0x00000014 ++#define VIDEO_OUT_CFG_INTR_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTR_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTR_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTR_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTR_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTR_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTE ++// JTAG access : synchronous ++// Description : Interrupt Enable ++#define VIDEO_OUT_CFG_INTE_OFFSET 0x00000018 ++#define VIDEO_OUT_CFG_INTE_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTE_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTF ++// JTAG access : synchronous ++// Description : Interrupt Force ++#define VIDEO_OUT_CFG_INTF_OFFSET 0x0000001c ++#define VIDEO_OUT_CFG_INTF_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTF_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTF_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTF_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTF_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTF_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTS ++// JTAG access : synchronous ++// Description : Interrupt status after masking & forcing ++#define VIDEO_OUT_CFG_INTS_OFFSET 0x00000020 ++#define VIDEO_OUT_CFG_INTS_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTS_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTS_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTS_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTS_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_BLOCK_ID ++// JTAG access : synchronous ++// Description : Block Identifier ++// Hexadecimal representation of "VOCF" ++#define VIDEO_OUT_CFG_BLOCK_ID_OFFSET 0x00000024 ++#define VIDEO_OUT_CFG_BLOCK_ID_BITS 0xffffffff ++#define VIDEO_OUT_CFG_BLOCK_ID_RESET 0x564f4346 ++#define VIDEO_OUT_CFG_BLOCK_ID_MSB 31 ++#define VIDEO_OUT_CFG_BLOCK_ID_LSB 0 ++#define VIDEO_OUT_CFG_BLOCK_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INSTANCE_ID ++// JTAG access : synchronous ++// Description : Block Instance Identifier ++#define VIDEO_OUT_CFG_INSTANCE_ID_OFFSET 0x00000028 ++#define VIDEO_OUT_CFG_INSTANCE_ID_BITS 0x0000000f ++#define VIDEO_OUT_CFG_INSTANCE_ID_RESET 0x00000000 ++#define VIDEO_OUT_CFG_INSTANCE_ID_MSB 3 ++#define VIDEO_OUT_CFG_INSTANCE_ID_LSB 0 ++#define VIDEO_OUT_CFG_INSTANCE_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_AUTO ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_OFFSET 0x0000002c ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_RESET 0x00000007 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_PARALLEL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_OFFSET 0x00000030 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_RESET 0x00000006 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_CTRL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_OFFSET 0x00000034 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_TRIG ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_OFFSET 0x00000038 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_ACCESS "SC" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_DONE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_OFFSET 0x0000003c ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_VEC ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_DPI ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++ ++#define CFG_WRITE(reg, val) writel((val), vec->hw_base[RP1VEC_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++#define CFG_READ(reg) readl(vec->hw_base[RP1VEC_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++ ++void rp1vec_vidout_setup(struct rp1_vec *vec) ++{ ++ /* ++ * We assume DPI and VEC can't be used at the same time (due to ++ * clashing requirements for PLL_VIDEO, and potentially for VDAC). ++ * We therefore leave DPI memories powered down. ++ */ ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_DPI_BITS); ++ CFG_WRITE(VIDEO_OUT_CFG_TEST_OVERRIDE, 0x00000000); ++ ++ /* DPI->Pads; VEC->VDAC */ ++ CFG_WRITE(VIDEO_OUT_CFG_SEL, VIDEO_OUT_CFG_SEL_VDAC_MUX_BITS); ++ ++ /* configure VDAC for 1 channel, bandgap on, 1.28V swing */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0x0019ffff); ++ ++ /* enable VEC interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, VIDEO_OUT_CFG_INTE_VEC_BITS); ++} ++ ++void rp1vec_vidout_poweroff(struct rp1_vec *vec) ++{ ++ /* disable VEC interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, 0); ++ ++ /* Ensure VDAC is turned off; power down DPI,VEC memories */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0); ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_BITS); ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c +@@ -0,0 +1,469 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for VEC output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_vec.h" ++#include "vec_regs.h" ++ ++#define BITS(field, val) (((val) << (field ## _LSB)) & (field ## _BITS)) ++ ++#define VEC_WRITE(reg, val) writel((val), vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET)) ++#define VEC_READ(reg) readl(vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET)) ++ ++int rp1vec_hw_busy(struct rp1_vec *vec) ++{ ++ /* Read the undocumented "pline_busy" flag */ ++ return VEC_READ(VEC_STATUS) & 1; ++} ++ ++/* Table of supported input (in-memory/DMA) pixel formats. */ ++struct rp1vec_ipixfmt { ++ u32 format; /* DRM format code */ ++ u32 mask; /* RGB masks (10 bits each, left justified) */ ++ u32 shift; /* RGB MSB positions in the memory word */ ++ u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */ ++}; ++ ++#define MASK_RGB(r, g, b) \ ++ (BITS(VEC_IMASK_MASK_R, r) | BITS(VEC_IMASK_MASK_G, g) | BITS(VEC_IMASK_MASK_B, b)) ++#define SHIFT_RGB(r, g, b) \ ++ (BITS(VEC_SHIFT_SHIFT_R, r) | BITS(VEC_SHIFT_SHIFT_G, g) | BITS(VEC_SHIFT_SHIFT_B, b)) ++ ++static const struct rp1vec_ipixfmt my_formats[] = { ++ { ++ .format = DRM_FORMAT_XRGB8888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 3), ++ }, ++ { ++ .format = DRM_FORMAT_XBGR8888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 3), ++ }, ++ { ++ .format = DRM_FORMAT_RGB888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 2), ++ }, ++ { ++ .format = DRM_FORMAT_BGR888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 2), ++ }, ++ { ++ .format = DRM_FORMAT_RGB565, ++ .mask = MASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = SHIFT_RGB(15, 10, 4), ++ .rgbsz = BITS(VEC_RGBSZ_SCALE_R, 5) | ++ BITS(VEC_RGBSZ_SCALE_G, 6) | ++ BITS(VEC_RGBSZ_SCALE_B, 5) | ++ BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 1), ++ } ++}; ++ ++/* ++ * Hardware mode descriptions (@ 108 MHz clock rate). ++ * These rely largely on "canned" register settings. ++ * TODO: Port the generating software from FP to integer, ++ * or better factorize the differences between modes. ++ */ ++ ++struct rp1vec_hwmode { ++ u16 total_cols; /* active columns, plus padding for filter context */ ++ u16 rows_per_field; /* active lines per field (including partial ones) */ ++ bool interlaced; /* set for interlaced */ ++ bool first_field_odd; /* set for interlaced and 30fps */ ++ u32 yuv_scaling; /* three 10-bit fields {Y, U, V} in 2.8 format */ ++ u32 back_end_regs[28]; /* All registers 0x80 .. 0xEC */ ++}; ++ ++/* { NTSC, PAL, PAL-M } x { progressive, interlaced } x { 13.5 MHz, 15.428571 MHz } */ ++static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = { ++ { ++ /* NTSC */ ++ { ++ { ++ .total_cols = 724, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1071d0cf, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x004c020e, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ec, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1c131962, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x004c020e, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ac, ++ }, ++ }, ++ }, { ++ { ++ .total_cols = 724, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x1071d0cf, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0107, 0x0111020d, 0x00000000, 0x00000000, ++ 0x011c020d, 0x00150106, 0x0107011b, 0x004c020d, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x00094dee, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x1c131962, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0107, 0x0111020d, 0x00000000, 0x00000000, ++ 0x011c020d, 0x00150106, 0x0107011b, 0x004c020d, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x00094dae, ++ }, ++ }, ++ }, ++ }, { ++ /* PAL */ ++ { ++ { ++ .total_cols = 724, ++ .rows_per_field = 288, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x04061aa6, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170136, 0x00000000, 0x000a0270, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ed, ++ }, ++ }, { ++ .total_cols = 804, ++ .rows_per_field = 288, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x045b1a57, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170136, 0x00000000, 0x000a0270, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ad, ++ }, ++ }, ++ }, { ++ { ++ .total_cols = 724, ++ .rows_per_field = 288, ++ .interlaced = true, ++ .first_field_odd = false, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x04061aa6, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x013f026d, 0x00060136, 0x0140026e, ++ 0x0150026e, 0x00180136, 0x026f0017, 0x000a0271, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddef, ++ }, ++ }, { ++ .total_cols = 804, ++ .rows_per_field = 288, ++ .interlaced = true, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x045b1a57, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x013f026d, 0x00060136, 0x0140026e, ++ 0x0150026e, 0x00180136, 0x026f0017, 0x000a0271, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddaf, ++ }, ++ }, ++ }, ++ }, { ++ /* PAL-M */ ++ { ++ { ++ .total_cols = 724, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x000a020c, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ed, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x000a020c, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ad, ++ }, ++ }, ++ }, { ++ { ++ .total_cols = 724, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00140019, 0x00000005, 0x0006000b, ++ 0x00090103, 0x010f0209, 0x00080102, 0x010e020a, ++ 0x0119020a, 0x00120103, 0x01040118, 0x000a020d, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddef, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00140019, 0x00000005, 0x0006000b, ++ 0x00090103, 0x010f0209, 0x00080102, 0x010e020a, ++ 0x0119020a, 0x00120103, 0x01040118, 0x000a020d, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddaf, ++ }, ++ }, ++ }, ++ }, ++}; ++ ++void rp1vec_hw_setup(struct rp1_vec *vec, ++ u32 in_format, ++ struct drm_display_mode const *mode, ++ int tvstd) ++{ ++ unsigned int i, mode_family, mode_ilaced, mode_narrow; ++ const struct rp1vec_hwmode *hwm; ++ unsigned int w, h; ++ ++ /* Pick the appropriate "base" mode, which we may modify */ ++ mode_ilaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); ++ if (mode->vtotal > 263 * (1 + mode_ilaced)) ++ mode_family = 1; ++ else ++ mode_family = (tvstd == RP1VEC_TVSTD_PAL_M || tvstd == RP1VEC_TVSTD_PAL60) ? 2 : 0; ++ mode_narrow = (mode->clock >= 14336); ++ hwm = &rp1vec_hwmodes[mode_family][mode_ilaced][mode_narrow]; ++ dev_info(&vec->pdev->dev, ++ "%s: in_fmt=\'%c%c%c%c\' mode=%dx%d%s [%d%d%d] tvstd=%d (%s)", ++ __func__, in_format, in_format >> 8, in_format >> 16, in_format >> 24, ++ mode->hdisplay, mode->vdisplay, (mode_ilaced) ? "i" : "", ++ mode_family, mode_ilaced, mode_narrow, ++ tvstd, rp1vec_tvstd_names[tvstd]); ++ ++ w = mode->hdisplay; ++ h = mode->vdisplay; ++ if (mode_ilaced) ++ h >>= 1; ++ if (w > hwm->total_cols) ++ w = hwm->total_cols; ++ if (h > hwm->rows_per_field) ++ w = hwm->rows_per_field; ++ ++ /* Configure the hardware */ ++ VEC_WRITE(VEC_APB_TIMEOUT, 0x38); ++ VEC_WRITE(VEC_QOS, ++ BITS(VEC_QOS_DQOS, 0x0) | ++ BITS(VEC_QOS_ULEV, 0x8) | ++ BITS(VEC_QOS_UQOS, 0x2) | ++ BITS(VEC_QOS_LLEV, 0x4) | ++ BITS(VEC_QOS_LQOS, 0x7)); ++ VEC_WRITE(VEC_DMA_AREA, ++ BITS(VEC_DMA_AREA_COLS_MINUS1, w - 1) | ++ BITS(VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1, h - 1)); ++ VEC_WRITE(VEC_YUV_SCALING, hwm->yuv_scaling); ++ VEC_WRITE(VEC_BACK_PORCH, ++ BITS(VEC_BACK_PORCH_HBP_MINUS1, (hwm->total_cols - w - 1) >> 1) | ++ BITS(VEC_BACK_PORCH_VBP_MINUS1, (hwm->rows_per_field - h - 1) >> 1)); ++ VEC_WRITE(VEC_FRONT_PORCH, ++ BITS(VEC_FRONT_PORCH_HFP_MINUS1, (hwm->total_cols - w - 2) >> 1) | ++ BITS(VEC_FRONT_PORCH_VFP_MINUS1, (hwm->rows_per_field - h - 2) >> 1)); ++ VEC_WRITE(VEC_MODE, ++ BITS(VEC_MODE_HIGH_WATER, 0xE0) | ++ BITS(VEC_MODE_ALIGN16, !((w | mode->hdisplay) & 15)) | ++ BITS(VEC_MODE_VFP_EN, (hwm->rows_per_field > h + 1)) | ++ BITS(VEC_MODE_VBP_EN, (hwm->rows_per_field > h)) | ++ BITS(VEC_MODE_HFP_EN, (hwm->total_cols > w + 1)) | ++ BITS(VEC_MODE_HBP_EN, (hwm->total_cols > w)) | ++ BITS(VEC_MODE_FIELDS_PER_FRAME_MINUS1, hwm->interlaced) | ++ BITS(VEC_MODE_FIRST_FIELD_ODD, hwm->first_field_odd)); ++ for (i = 0; i < ARRAY_SIZE(hwm->back_end_regs); ++i) { ++ writel(hwm->back_end_regs[i], ++ vec->hw_base[RP1VEC_HW_BLOCK_VEC] + 0x80 + 4 * i); ++ } ++ ++ /* Apply modifications */ ++ if (tvstd == RP1VEC_TVSTD_NTSC_J && mode_family == 0) { ++ /* Reduce pedestal (not quite to zero, for FIR overshoot); increase gain */ ++ VEC_WRITE(VEC_DAC_BC, ++ BITS(VEC_DAC_BC_S11_PEDESTAL, 10) | ++ (hwm->back_end_regs[(0xBC - 0x80) / 4] & ~VEC_DAC_BC_S11_PEDESTAL_BITS)); ++ VEC_WRITE(VEC_DAC_C8, ++ BITS(VEC_DAC_C8_U16_SCALE_LUMA, 0x9400) | ++ (hwm->back_end_regs[(0xC8 - 0x80) / 4] & ++ ~VEC_DAC_C8_U16_SCALE_LUMA_BITS)); ++ } else if ((tvstd == RP1VEC_TVSTD_NTSC_443 || tvstd == RP1VEC_TVSTD_PAL60) && ++ mode_family != 1) { ++ /* Change colour carrier frequency to 4433618.75 Hz; disable hard sync */ ++ VEC_WRITE(VEC_DAC_D4, 0xcc48c1d1); ++ VEC_WRITE(VEC_DAC_D8, 0x0a8262b2); ++ VEC_WRITE(VEC_DAC_EC, ++ hwm->back_end_regs[(0xEC - 0x80) / 4] & ~VEC_DAC_EC_SEQ_EN_BITS); ++ } else if (tvstd == RP1VEC_TVSTD_PAL_N && mode_family == 1) { ++ /* Change colour carrier frequency to 3582056.25 Hz */ ++ VEC_WRITE(VEC_DAC_D4, 0x9ce075f7); ++ VEC_WRITE(VEC_DAC_D8, 0x087da511); ++ } ++ ++ /* Input pixel format conversion */ ++ for (i = 0; i < ARRAY_SIZE(my_formats); ++i) { ++ if (my_formats[i].format == in_format) ++ break; ++ } ++ if (i >= ARRAY_SIZE(my_formats)) { ++ dev_err(&vec->pdev->dev, "%s: bad input format\n", __func__); ++ i = 0; ++ } ++ VEC_WRITE(VEC_IMASK, my_formats[i].mask); ++ VEC_WRITE(VEC_SHIFT, my_formats[i].shift); ++ VEC_WRITE(VEC_RGBSZ, my_formats[i].rgbsz); ++ ++ VEC_WRITE(VEC_IRQ_FLAGS, 0xffffffff); ++ rp1vec_hw_vblank_ctrl(vec, 1); ++ ++ i = rp1vec_hw_busy(vec); ++ if (i) ++ dev_warn(&vec->pdev->dev, ++ "%s: VEC unexpectedly busy at start (0x%08x)", ++ __func__, VEC_READ(VEC_STATUS)); ++ ++ VEC_WRITE(VEC_CONTROL, ++ BITS(VEC_CONTROL_START_ARM, (!i)) | ++ BITS(VEC_CONTROL_AUTO_REPEAT, 1)); ++} ++ ++void rp1vec_hw_update(struct rp1_vec *vec, dma_addr_t addr, u32 offset, u32 stride) ++{ ++ /* ++ * Update STRIDE, DMAH and DMAL only. When called after rp1vec_hw_setup(), ++ * DMA starts immediately; if already running, the buffer will flip at ++ * the next vertical sync event. ++ */ ++ u64 a = addr + offset; ++ ++ VEC_WRITE(VEC_DMA_STRIDE, stride); ++ VEC_WRITE(VEC_DMA_ADDR_H, a >> 32); ++ VEC_WRITE(VEC_DMA_ADDR_L, a & 0xFFFFFFFFu); ++} ++ ++void rp1vec_hw_stop(struct rp1_vec *vec) ++{ ++ /* ++ * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for ++ * the current and any queued frame to end. "Force drain" flags are not used, ++ * as they seem to prevent DMA from re-starting properly; it's safer to wait. ++ */ ++ ++ reinit_completion(&vec->finished); ++ VEC_WRITE(VEC_CONTROL, 0); ++ if (!wait_for_completion_timeout(&vec->finished, HZ / 10)) ++ drm_err(vec->drm, "%s: timed out waiting for idle\n", __func__); ++ VEC_WRITE(VEC_IRQ_ENABLES, 0); ++} ++ ++void rp1vec_hw_vblank_ctrl(struct rp1_vec *vec, int enable) ++{ ++ VEC_WRITE(VEC_IRQ_ENABLES, ++ BITS(VEC_IRQ_ENABLES_DONE, 1) | ++ BITS(VEC_IRQ_ENABLES_DMA, (enable ? 1 : 0)) | ++ BITS(VEC_IRQ_ENABLES_MATCH_ROW, 1023)); ++} ++ ++irqreturn_t rp1vec_hw_isr(int irq, void *dev) ++{ ++ struct rp1_vec *vec = dev; ++ u32 u = VEC_READ(VEC_IRQ_FLAGS); ++ ++ if (u) { ++ VEC_WRITE(VEC_IRQ_FLAGS, u); ++ if (u & VEC_IRQ_FLAGS_DMA_BITS) ++ drm_crtc_handle_vblank(&vec->pipe.crtc); ++ if (u & VEC_IRQ_FLAGS_DONE_BITS) ++ complete(&vec->finished); ++ } ++ return u ? IRQ_HANDLED : IRQ_NONE; ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/vec_regs.h +@@ -0,0 +1,1420 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++// ============================================================================= ++// Copyright Raspberry Pi Ltd. 2023 ++// vrbuild version: 56aac1a23c016cbbd229108f3b6efc1343842156-clean ++// THIS FILE IS GENERATED BY VRBUILD - DO NOT EDIT ++// ============================================================================= ++// Register block : VEC ++// Version : 1 ++// Bus type : apb ++// Description : None ++// ============================================================================= ++#ifndef VEC_REGS_DEFINED ++#define VEC_REGS_DEFINED ++#define VEC_REGS_RWTYPE_MSB 13 ++#define VEC_REGS_RWTYPE_LSB 12 ++// ============================================================================= ++// Register : VEC_CONTROL ++// JTAG access : synchronous ++// Description : None ++#define VEC_CONTROL_OFFSET 0x00000000 ++#define VEC_CONTROL_BITS 0x00000007 ++#define VEC_CONTROL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_CONTROL_BARS ++// Description : Write '1' to display colour bar test pattern ++#define VEC_CONTROL_BARS_RESET 0x0 ++#define VEC_CONTROL_BARS_BITS 0x00000004 ++#define VEC_CONTROL_BARS_MSB 2 ++#define VEC_CONTROL_BARS_LSB 2 ++#define VEC_CONTROL_BARS_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_CONTROL_AUTO_REPEAT ++// Description : Write '1' to re-display same frame continuously ++#define VEC_CONTROL_AUTO_REPEAT_RESET 0x0 ++#define VEC_CONTROL_AUTO_REPEAT_BITS 0x00000002 ++#define VEC_CONTROL_AUTO_REPEAT_MSB 1 ++#define VEC_CONTROL_AUTO_REPEAT_LSB 1 ++#define VEC_CONTROL_AUTO_REPEAT_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_CONTROL_START_ARM ++// Description : Write '1' before first DMA address is written This bit always ++// reads back as '0' ++#define VEC_CONTROL_START_ARM_RESET 0x0 ++#define VEC_CONTROL_START_ARM_BITS 0x00000001 ++#define VEC_CONTROL_START_ARM_MSB 0 ++#define VEC_CONTROL_START_ARM_LSB 0 ++#define VEC_CONTROL_START_ARM_ACCESS "SC" ++// ============================================================================= ++// Register : VEC_IRQ_ENABLES ++// JTAG access : synchronous ++// Description : None ++#define VEC_IRQ_ENABLES_OFFSET 0x00000004 ++#define VEC_IRQ_ENABLES_BITS 0x03ff003f ++#define VEC_IRQ_ENABLES_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_MATCH_ROW ++// Description : Raster line at which MATCH interrupt is signalled ++#define VEC_IRQ_ENABLES_MATCH_ROW_RESET 0x000 ++#define VEC_IRQ_ENABLES_MATCH_ROW_BITS 0x03ff0000 ++#define VEC_IRQ_ENABLES_MATCH_ROW_MSB 25 ++#define VEC_IRQ_ENABLES_MATCH_ROW_LSB 16 ++#define VEC_IRQ_ENABLES_MATCH_ROW_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_MATCH ++// Description : Output raster == match_row reached ++#define VEC_IRQ_ENABLES_MATCH_RESET 0x0 ++#define VEC_IRQ_ENABLES_MATCH_BITS 0x00000020 ++#define VEC_IRQ_ENABLES_MATCH_MSB 5 ++#define VEC_IRQ_ENABLES_MATCH_LSB 5 ++#define VEC_IRQ_ENABLES_MATCH_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_ERROR ++// Description : DMA address overwritten before it was taken ++#define VEC_IRQ_ENABLES_ERROR_RESET 0x0 ++#define VEC_IRQ_ENABLES_ERROR_BITS 0x00000010 ++#define VEC_IRQ_ENABLES_ERROR_MSB 4 ++#define VEC_IRQ_ENABLES_ERROR_LSB 4 ++#define VEC_IRQ_ENABLES_ERROR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_DONE ++// Description : Last word sent to DAC after end of video (= all clear) ++#define VEC_IRQ_ENABLES_DONE_RESET 0x0 ++#define VEC_IRQ_ENABLES_DONE_BITS 0x00000008 ++#define VEC_IRQ_ENABLES_DONE_MSB 3 ++#define VEC_IRQ_ENABLES_DONE_LSB 3 ++#define VEC_IRQ_ENABLES_DONE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_FRAME ++// Description : Start of frame ++#define VEC_IRQ_ENABLES_FRAME_RESET 0x0 ++#define VEC_IRQ_ENABLES_FRAME_BITS 0x00000004 ++#define VEC_IRQ_ENABLES_FRAME_MSB 2 ++#define VEC_IRQ_ENABLES_FRAME_LSB 2 ++#define VEC_IRQ_ENABLES_FRAME_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_UNDERFLOW ++// Description : Underflow has occurred ++#define VEC_IRQ_ENABLES_UNDERFLOW_RESET 0x0 ++#define VEC_IRQ_ENABLES_UNDERFLOW_BITS 0x00000002 ++#define VEC_IRQ_ENABLES_UNDERFLOW_MSB 1 ++#define VEC_IRQ_ENABLES_UNDERFLOW_LSB 1 ++#define VEC_IRQ_ENABLES_UNDERFLOW_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_DMA ++// Description : DMA ready to accept next frame start address ++#define VEC_IRQ_ENABLES_DMA_RESET 0x0 ++#define VEC_IRQ_ENABLES_DMA_BITS 0x00000001 ++#define VEC_IRQ_ENABLES_DMA_MSB 0 ++#define VEC_IRQ_ENABLES_DMA_LSB 0 ++#define VEC_IRQ_ENABLES_DMA_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_IRQ_FLAGS ++// JTAG access : synchronous ++// Description : None ++#define VEC_IRQ_FLAGS_OFFSET 0x00000008 ++#define VEC_IRQ_FLAGS_BITS 0x0000003f ++#define VEC_IRQ_FLAGS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_MATCH ++// Description : Output raster == match_row reached ++#define VEC_IRQ_FLAGS_MATCH_RESET 0x0 ++#define VEC_IRQ_FLAGS_MATCH_BITS 0x00000020 ++#define VEC_IRQ_FLAGS_MATCH_MSB 5 ++#define VEC_IRQ_FLAGS_MATCH_LSB 5 ++#define VEC_IRQ_FLAGS_MATCH_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_ERROR ++// Description : DMA address overwritten before it was taken ++#define VEC_IRQ_FLAGS_ERROR_RESET 0x0 ++#define VEC_IRQ_FLAGS_ERROR_BITS 0x00000010 ++#define VEC_IRQ_FLAGS_ERROR_MSB 4 ++#define VEC_IRQ_FLAGS_ERROR_LSB 4 ++#define VEC_IRQ_FLAGS_ERROR_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_DONE ++// Description : Last word sent to DAC after end of video (= all clear) ++#define VEC_IRQ_FLAGS_DONE_RESET 0x0 ++#define VEC_IRQ_FLAGS_DONE_BITS 0x00000008 ++#define VEC_IRQ_FLAGS_DONE_MSB 3 ++#define VEC_IRQ_FLAGS_DONE_LSB 3 ++#define VEC_IRQ_FLAGS_DONE_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_FRAME ++// Description : Start of frame ++#define VEC_IRQ_FLAGS_FRAME_RESET 0x0 ++#define VEC_IRQ_FLAGS_FRAME_BITS 0x00000004 ++#define VEC_IRQ_FLAGS_FRAME_MSB 2 ++#define VEC_IRQ_FLAGS_FRAME_LSB 2 ++#define VEC_IRQ_FLAGS_FRAME_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_UNDERFLOW ++// Description : Underflow has occurred ++#define VEC_IRQ_FLAGS_UNDERFLOW_RESET 0x0 ++#define VEC_IRQ_FLAGS_UNDERFLOW_BITS 0x00000002 ++#define VEC_IRQ_FLAGS_UNDERFLOW_MSB 1 ++#define VEC_IRQ_FLAGS_UNDERFLOW_LSB 1 ++#define VEC_IRQ_FLAGS_UNDERFLOW_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_DMA ++// Description : DMA ready to accept next frame start address ++#define VEC_IRQ_FLAGS_DMA_RESET 0x0 ++#define VEC_IRQ_FLAGS_DMA_BITS 0x00000001 ++#define VEC_IRQ_FLAGS_DMA_MSB 0 ++#define VEC_IRQ_FLAGS_DMA_LSB 0 ++#define VEC_IRQ_FLAGS_DMA_ACCESS "WC" ++// ============================================================================= ++// Register : VEC_QOS ++// JTAG access : synchronous ++// Description : This register configures panic levels for the AXI ar_qos ++// quality of service field. Panic status is driven by the number ++// of rows held in the SRAM cache: ++#define VEC_QOS_OFFSET 0x0000000c ++#define VEC_QOS_BITS 0x000fffff ++#define VEC_QOS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_UQOS ++// Description : Upper AXI QOS ++#define VEC_QOS_UQOS_RESET 0x0 ++#define VEC_QOS_UQOS_BITS 0x000f0000 ++#define VEC_QOS_UQOS_MSB 19 ++#define VEC_QOS_UQOS_LSB 16 ++#define VEC_QOS_UQOS_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_ULEV ++// Description : Upper trip level (resolution = 1 / 16 of cache size) ++#define VEC_QOS_ULEV_RESET 0x0 ++#define VEC_QOS_ULEV_BITS 0x0000f000 ++#define VEC_QOS_ULEV_MSB 15 ++#define VEC_QOS_ULEV_LSB 12 ++#define VEC_QOS_ULEV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_LQOS ++// Description : Lower AXI QOS ++#define VEC_QOS_LQOS_RESET 0x0 ++#define VEC_QOS_LQOS_BITS 0x00000f00 ++#define VEC_QOS_LQOS_MSB 11 ++#define VEC_QOS_LQOS_LSB 8 ++#define VEC_QOS_LQOS_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_LLEV ++// Description : Lower trip level (resolution = 1 / 16 of cache size) ++#define VEC_QOS_LLEV_RESET 0x0 ++#define VEC_QOS_LLEV_BITS 0x000000f0 ++#define VEC_QOS_LLEV_MSB 7 ++#define VEC_QOS_LLEV_LSB 4 ++#define VEC_QOS_LLEV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_DQOS ++// Description : Default QOS ++#define VEC_QOS_DQOS_RESET 0x0 ++#define VEC_QOS_DQOS_BITS 0x0000000f ++#define VEC_QOS_DQOS_MSB 3 ++#define VEC_QOS_DQOS_LSB 0 ++#define VEC_QOS_DQOS_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DMA_ADDR_L ++// JTAG access : synchronous ++// Description : Lower 32-bits ++#define VEC_DMA_ADDR_L_OFFSET 0x00000010 ++#define VEC_DMA_ADDR_L_BITS 0xffffffff ++#define VEC_DMA_ADDR_L_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_ADDR_L_AXI_ADDR ++// Description : Byte address of DMA transfer frame buffer. ++#define VEC_DMA_ADDR_L_AXI_ADDR_RESET 0x00000000 ++#define VEC_DMA_ADDR_L_AXI_ADDR_BITS 0xffffffff ++#define VEC_DMA_ADDR_L_AXI_ADDR_MSB 31 ++#define VEC_DMA_ADDR_L_AXI_ADDR_LSB 0 ++#define VEC_DMA_ADDR_L_AXI_ADDR_ACCESS "RWF" ++// ============================================================================= ++// Register : VEC_DMA_STRIDE ++// JTAG access : synchronous ++// Description : This register sets the line byte stride. ++#define VEC_DMA_STRIDE_OFFSET 0x00000014 ++#define VEC_DMA_STRIDE_BITS 0xffffffff ++#define VEC_DMA_STRIDE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_STRIDE_STRIDE ++// Description : Byte stride ++#define VEC_DMA_STRIDE_STRIDE_RESET 0x00000000 ++#define VEC_DMA_STRIDE_STRIDE_BITS 0xffffffff ++#define VEC_DMA_STRIDE_STRIDE_MSB 31 ++#define VEC_DMA_STRIDE_STRIDE_LSB 0 ++#define VEC_DMA_STRIDE_STRIDE_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DMA_AREA ++// JTAG access : synchronous ++// Description : Interlaced pixel area. See example driver code. ++#define VEC_DMA_AREA_OFFSET 0x00000018 ++#define VEC_DMA_AREA_BITS 0x03ff03ff ++#define VEC_DMA_AREA_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_AREA_COLS_MINUS1 ++// Description : Width ++#define VEC_DMA_AREA_COLS_MINUS1_RESET 0x000 ++#define VEC_DMA_AREA_COLS_MINUS1_BITS 0x03ff0000 ++#define VEC_DMA_AREA_COLS_MINUS1_MSB 25 ++#define VEC_DMA_AREA_COLS_MINUS1_LSB 16 ++#define VEC_DMA_AREA_COLS_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1 ++// Description : Lines per field = half of lines per interlaced frame ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_RESET 0x000 ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_BITS 0x000003ff ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_MSB 9 ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_LSB 0 ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_YUV_SCALING ++// JTAG access : synchronous ++// Description : None ++#define VEC_YUV_SCALING_OFFSET 0x0000001c ++#define VEC_YUV_SCALING_BITS 0x3fffffff ++#define VEC_YUV_SCALING_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_YUV_SCALING_U10_SCALE_Y ++// Description : Y unsigned scaling factor - 8 binary places ++#define VEC_YUV_SCALING_U10_SCALE_Y_RESET 0x000 ++#define VEC_YUV_SCALING_U10_SCALE_Y_BITS 0x3ff00000 ++#define VEC_YUV_SCALING_U10_SCALE_Y_MSB 29 ++#define VEC_YUV_SCALING_U10_SCALE_Y_LSB 20 ++#define VEC_YUV_SCALING_U10_SCALE_Y_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_YUV_SCALING_S10_SCALE_U ++// Description : U signed scaling factor - 8 binary places ++#define VEC_YUV_SCALING_S10_SCALE_U_RESET 0x000 ++#define VEC_YUV_SCALING_S10_SCALE_U_BITS 0x000ffc00 ++#define VEC_YUV_SCALING_S10_SCALE_U_MSB 19 ++#define VEC_YUV_SCALING_S10_SCALE_U_LSB 10 ++#define VEC_YUV_SCALING_S10_SCALE_U_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_YUV_SCALING_S10_SCALE_V ++// Description : V signed scaling factor - 8 binary please ++#define VEC_YUV_SCALING_S10_SCALE_V_RESET 0x000 ++#define VEC_YUV_SCALING_S10_SCALE_V_BITS 0x000003ff ++#define VEC_YUV_SCALING_S10_SCALE_V_MSB 9 ++#define VEC_YUV_SCALING_S10_SCALE_V_LSB 0 ++#define VEC_YUV_SCALING_S10_SCALE_V_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_BACK_PORCH ++// JTAG access : synchronous ++// Description : None ++#define VEC_BACK_PORCH_OFFSET 0x00000020 ++#define VEC_BACK_PORCH_BITS 0x03ff03ff ++#define VEC_BACK_PORCH_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_BACK_PORCH_HBP_MINUS1 ++// Description : Horizontal back porch ++#define VEC_BACK_PORCH_HBP_MINUS1_RESET 0x000 ++#define VEC_BACK_PORCH_HBP_MINUS1_BITS 0x03ff0000 ++#define VEC_BACK_PORCH_HBP_MINUS1_MSB 25 ++#define VEC_BACK_PORCH_HBP_MINUS1_LSB 16 ++#define VEC_BACK_PORCH_HBP_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_BACK_PORCH_VBP_MINUS1 ++// Description : Vertical back porch ++#define VEC_BACK_PORCH_VBP_MINUS1_RESET 0x000 ++#define VEC_BACK_PORCH_VBP_MINUS1_BITS 0x000003ff ++#define VEC_BACK_PORCH_VBP_MINUS1_MSB 9 ++#define VEC_BACK_PORCH_VBP_MINUS1_LSB 0 ++#define VEC_BACK_PORCH_VBP_MINUS1_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_FRONT_PORCH ++// JTAG access : synchronous ++// Description : None ++#define VEC_FRONT_PORCH_OFFSET 0x00000024 ++#define VEC_FRONT_PORCH_BITS 0x03ff03ff ++#define VEC_FRONT_PORCH_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_FRONT_PORCH_HFP_MINUS1 ++// Description : Horizontal front porch ++#define VEC_FRONT_PORCH_HFP_MINUS1_RESET 0x000 ++#define VEC_FRONT_PORCH_HFP_MINUS1_BITS 0x03ff0000 ++#define VEC_FRONT_PORCH_HFP_MINUS1_MSB 25 ++#define VEC_FRONT_PORCH_HFP_MINUS1_LSB 16 ++#define VEC_FRONT_PORCH_HFP_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_FRONT_PORCH_VFP_MINUS1 ++// Description : Vertical front porch ++#define VEC_FRONT_PORCH_VFP_MINUS1_RESET 0x000 ++#define VEC_FRONT_PORCH_VFP_MINUS1_BITS 0x000003ff ++#define VEC_FRONT_PORCH_VFP_MINUS1_MSB 9 ++#define VEC_FRONT_PORCH_VFP_MINUS1_LSB 0 ++#define VEC_FRONT_PORCH_VFP_MINUS1_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_SHIFT ++// JTAG access : synchronous ++// Description : Positions of R,G,B MS bits in the memory word. Note: due to an ++// unintended red/blue swap, these fields have been renamed since ++// a previous version. There is no functional change. ++#define VEC_SHIFT_OFFSET 0x00000028 ++#define VEC_SHIFT_BITS 0x00007fff ++#define VEC_SHIFT_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_SHIFT_SHIFT_R ++// Description : Red MSB ++#define VEC_SHIFT_SHIFT_R_RESET 0x00 ++#define VEC_SHIFT_SHIFT_R_BITS 0x00007c00 ++#define VEC_SHIFT_SHIFT_R_MSB 14 ++#define VEC_SHIFT_SHIFT_R_LSB 10 ++#define VEC_SHIFT_SHIFT_R_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_SHIFT_SHIFT_G ++// Description : Green MSB ++#define VEC_SHIFT_SHIFT_G_RESET 0x00 ++#define VEC_SHIFT_SHIFT_G_BITS 0x000003e0 ++#define VEC_SHIFT_SHIFT_G_MSB 9 ++#define VEC_SHIFT_SHIFT_G_LSB 5 ++#define VEC_SHIFT_SHIFT_G_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_SHIFT_SHIFT_B ++// Description : Blue MSB ++#define VEC_SHIFT_SHIFT_B_RESET 0x00 ++#define VEC_SHIFT_SHIFT_B_BITS 0x0000001f ++#define VEC_SHIFT_SHIFT_B_MSB 4 ++#define VEC_SHIFT_SHIFT_B_LSB 0 ++#define VEC_SHIFT_SHIFT_B_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_IMASK ++// JTAG access : synchronous ++// Description : Masks for R,G,B significant bits, left-justified within 10-bit ++// fields. ++#define VEC_IMASK_OFFSET 0x0000002c ++#define VEC_IMASK_BITS 0x3fffffff ++#define VEC_IMASK_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_IMASK_MASK_R ++// Description : Red mask ++#define VEC_IMASK_MASK_R_RESET 0x000 ++#define VEC_IMASK_MASK_R_BITS 0x3ff00000 ++#define VEC_IMASK_MASK_R_MSB 29 ++#define VEC_IMASK_MASK_R_LSB 20 ++#define VEC_IMASK_MASK_R_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IMASK_MASK_G ++// Description : Green mask ++#define VEC_IMASK_MASK_G_RESET 0x000 ++#define VEC_IMASK_MASK_G_BITS 0x000ffc00 ++#define VEC_IMASK_MASK_G_MSB 19 ++#define VEC_IMASK_MASK_G_LSB 10 ++#define VEC_IMASK_MASK_G_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IMASK_MASK_B ++// Description : Blue mask ++#define VEC_IMASK_MASK_B_RESET 0x000 ++#define VEC_IMASK_MASK_B_BITS 0x000003ff ++#define VEC_IMASK_MASK_B_MSB 9 ++#define VEC_IMASK_MASK_B_LSB 0 ++#define VEC_IMASK_MASK_B_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_MODE ++// JTAG access : synchronous ++// Description : None ++#define VEC_MODE_OFFSET 0x00000030 ++#define VEC_MODE_BITS 0x01ff003f ++#define VEC_MODE_RESET 0x01c00000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_HIGH_WATER ++// Description : ALWAYS WRITE 8'hE0 ++#define VEC_MODE_HIGH_WATER_RESET 0xe0 ++#define VEC_MODE_HIGH_WATER_BITS 0x01fe0000 ++#define VEC_MODE_HIGH_WATER_MSB 24 ++#define VEC_MODE_HIGH_WATER_LSB 17 ++#define VEC_MODE_HIGH_WATER_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_ALIGN16 ++// Description : Data: 0=BYTE aligned; 1=BEAT aligned ++#define VEC_MODE_ALIGN16_RESET 0x0 ++#define VEC_MODE_ALIGN16_BITS 0x00010000 ++#define VEC_MODE_ALIGN16_MSB 16 ++#define VEC_MODE_ALIGN16_LSB 16 ++#define VEC_MODE_ALIGN16_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_VFP_EN ++// Description : Enable vertical front porch ++#define VEC_MODE_VFP_EN_RESET 0x0 ++#define VEC_MODE_VFP_EN_BITS 0x00000020 ++#define VEC_MODE_VFP_EN_MSB 5 ++#define VEC_MODE_VFP_EN_LSB 5 ++#define VEC_MODE_VFP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_VBP_EN ++// Description : Enable vertical back porch ++#define VEC_MODE_VBP_EN_RESET 0x0 ++#define VEC_MODE_VBP_EN_BITS 0x00000010 ++#define VEC_MODE_VBP_EN_MSB 4 ++#define VEC_MODE_VBP_EN_LSB 4 ++#define VEC_MODE_VBP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_HFP_EN ++// Description : Enable horizontal front porch ++#define VEC_MODE_HFP_EN_RESET 0x0 ++#define VEC_MODE_HFP_EN_BITS 0x00000008 ++#define VEC_MODE_HFP_EN_MSB 3 ++#define VEC_MODE_HFP_EN_LSB 3 ++#define VEC_MODE_HFP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_HBP_EN ++// Description : Enable horizontal back porch ++#define VEC_MODE_HBP_EN_RESET 0x0 ++#define VEC_MODE_HBP_EN_BITS 0x00000004 ++#define VEC_MODE_HBP_EN_MSB 2 ++#define VEC_MODE_HBP_EN_LSB 2 ++#define VEC_MODE_HBP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_FIELDS_PER_FRAME_MINUS1 ++// Description : Interlaced / progressive ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_RESET 0x0 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_BITS 0x00000002 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_MSB 1 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_LSB 1 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_FIRST_FIELD_ODD ++// Description : Interlacing order: odd/even or even/odd ++#define VEC_MODE_FIRST_FIELD_ODD_RESET 0x0 ++#define VEC_MODE_FIRST_FIELD_ODD_BITS 0x00000001 ++#define VEC_MODE_FIRST_FIELD_ODD_MSB 0 ++#define VEC_MODE_FIRST_FIELD_ODD_LSB 0 ++#define VEC_MODE_FIRST_FIELD_ODD_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_RGBSZ ++// JTAG access : synchronous ++// Description : None ++#define VEC_RGBSZ_OFFSET 0x00000034 ++#define VEC_RGBSZ_BITS 0x00030fff ++#define VEC_RGBSZ_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1 ++// Description : Pixel stride ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_RESET 0x0 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_BITS 0x00030000 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_MSB 17 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_LSB 16 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_SCALE_R ++// Description : Red number of bits for shift-and-OR scaling ++#define VEC_RGBSZ_SCALE_R_RESET 0x0 ++#define VEC_RGBSZ_SCALE_R_BITS 0x00000f00 ++#define VEC_RGBSZ_SCALE_R_MSB 11 ++#define VEC_RGBSZ_SCALE_R_LSB 8 ++#define VEC_RGBSZ_SCALE_R_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_SCALE_G ++// Description : Green number of bits for shift-and-OR scaling ++#define VEC_RGBSZ_SCALE_G_RESET 0x0 ++#define VEC_RGBSZ_SCALE_G_BITS 0x000000f0 ++#define VEC_RGBSZ_SCALE_G_MSB 7 ++#define VEC_RGBSZ_SCALE_G_LSB 4 ++#define VEC_RGBSZ_SCALE_G_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_SCALE_B ++// Description : Blue number of bits for shift-and-OR scaling ++#define VEC_RGBSZ_SCALE_B_RESET 0x0 ++#define VEC_RGBSZ_SCALE_B_BITS 0x0000000f ++#define VEC_RGBSZ_SCALE_B_MSB 3 ++#define VEC_RGBSZ_SCALE_B_LSB 0 ++#define VEC_RGBSZ_SCALE_B_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_PANICS ++// JTAG access : synchronous ++// Description : None ++#define VEC_PANICS_OFFSET 0x00000038 ++#define VEC_PANICS_BITS 0xffffffff ++#define VEC_PANICS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_PANICS_UCOUNT ++// Description : Upper panic count ++#define VEC_PANICS_UCOUNT_RESET 0x0000 ++#define VEC_PANICS_UCOUNT_BITS 0xffff0000 ++#define VEC_PANICS_UCOUNT_MSB 31 ++#define VEC_PANICS_UCOUNT_LSB 16 ++#define VEC_PANICS_UCOUNT_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_PANICS_LCOUNT ++// Description : Lower panic count ++#define VEC_PANICS_LCOUNT_RESET 0x0000 ++#define VEC_PANICS_LCOUNT_BITS 0x0000ffff ++#define VEC_PANICS_LCOUNT_MSB 15 ++#define VEC_PANICS_LCOUNT_LSB 0 ++#define VEC_PANICS_LCOUNT_ACCESS "WC" ++// ============================================================================= ++// Register : VEC_STATUS ++// JTAG access : synchronous ++// Description : None ++#define VEC_STATUS_OFFSET 0x0000003c ++#define VEC_STATUS_BITS 0xff000000 ++#define VEC_STATUS_RESET 0x0d000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_STATUS_VERSION ++// Description : VEC module version code ++#define VEC_STATUS_VERSION_RESET 0x0d ++#define VEC_STATUS_VERSION_BITS 0xff000000 ++#define VEC_STATUS_VERSION_MSB 31 ++#define VEC_STATUS_VERSION_LSB 24 ++#define VEC_STATUS_VERSION_ACCESS "RO" ++// ============================================================================= ++// Register : VEC_DMA_ADDR_H ++// JTAG access : synchronous ++// Description : Upper 32-bits ++#define VEC_DMA_ADDR_H_OFFSET 0x00000040 ++#define VEC_DMA_ADDR_H_BITS 0xffffffff ++#define VEC_DMA_ADDR_H_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_ADDR_H_AXI_ADDR ++// Description : Byte address of DMA transfer frame buffer. ++#define VEC_DMA_ADDR_H_AXI_ADDR_RESET 0x00000000 ++#define VEC_DMA_ADDR_H_AXI_ADDR_BITS 0xffffffff ++#define VEC_DMA_ADDR_H_AXI_ADDR_MSB 31 ++#define VEC_DMA_ADDR_H_AXI_ADDR_LSB 0 ++#define VEC_DMA_ADDR_H_AXI_ADDR_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_BURST_ADDR_L ++// JTAG access : synchronous ++// Description : None ++#define VEC_BURST_ADDR_L_OFFSET 0x00000044 ++#define VEC_BURST_ADDR_L_BITS 0xffffffff ++#define VEC_BURST_ADDR_L_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_BURST_ADDR_L_BURST_ADDR ++// Description : the lower 32-bits of the most recent read request sent to AXI ++// memory. ++#define VEC_BURST_ADDR_L_BURST_ADDR_RESET 0x00000000 ++#define VEC_BURST_ADDR_L_BURST_ADDR_BITS 0xffffffff ++#define VEC_BURST_ADDR_L_BURST_ADDR_MSB 31 ++#define VEC_BURST_ADDR_L_BURST_ADDR_LSB 0 ++#define VEC_BURST_ADDR_L_BURST_ADDR_ACCESS "RO" ++// ============================================================================= ++// Register : VEC_APB_TIMEOUT ++// JTAG access : synchronous ++// Description : None ++#define VEC_APB_TIMEOUT_OFFSET 0x00000048 ++#define VEC_APB_TIMEOUT_BITS 0x000103ff ++#define VEC_APB_TIMEOUT_RESET 0x00000014 ++// ----------------------------------------------------------------------------- ++// Field : VEC_APB_TIMEOUT_SLVERR_EN ++// Description : 1 = Assert PREADY and PSLVERR on timeout 0 = Assert PREADY only ++#define VEC_APB_TIMEOUT_SLVERR_EN_RESET 0x0 ++#define VEC_APB_TIMEOUT_SLVERR_EN_BITS 0x00010000 ++#define VEC_APB_TIMEOUT_SLVERR_EN_MSB 16 ++#define VEC_APB_TIMEOUT_SLVERR_EN_LSB 16 ++#define VEC_APB_TIMEOUT_SLVERR_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_APB_TIMEOUT_TIMEOUT ++// Description : Maximum AXI clock cycles to wait for responses from DAC clock ++// domain APB block ++#define VEC_APB_TIMEOUT_TIMEOUT_RESET 0x014 ++#define VEC_APB_TIMEOUT_TIMEOUT_BITS 0x000003ff ++#define VEC_APB_TIMEOUT_TIMEOUT_MSB 9 ++#define VEC_APB_TIMEOUT_TIMEOUT_LSB 0 ++#define VEC_APB_TIMEOUT_TIMEOUT_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_80 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_80_OFFSET 0x00000080 ++#define VEC_DAC_80_BITS 0x3fff3fff ++#define VEC_DAC_80_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_80_U14_DE_BGN ++// Description : Beginning of active data enable within each visible line ++#define VEC_DAC_80_U14_DE_BGN_RESET 0x0000 ++#define VEC_DAC_80_U14_DE_BGN_BITS 0x3fff0000 ++#define VEC_DAC_80_U14_DE_BGN_MSB 29 ++#define VEC_DAC_80_U14_DE_BGN_LSB 16 ++#define VEC_DAC_80_U14_DE_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_80_U14_DE_END ++// Description : End of active data enable within each visible line ++#define VEC_DAC_80_U14_DE_END_RESET 0x0000 ++#define VEC_DAC_80_U14_DE_END_BITS 0x00003fff ++#define VEC_DAC_80_U14_DE_END_MSB 13 ++#define VEC_DAC_80_U14_DE_END_LSB 0 ++#define VEC_DAC_80_U14_DE_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_84 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_84_OFFSET 0x00000084 ++#define VEC_DAC_84_BITS 0x1fff1fff ++#define VEC_DAC_84_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_84_U13_ACTIVE_RISE ++// Description : Horizontal blanking interval ++#define VEC_DAC_84_U13_ACTIVE_RISE_RESET 0x0000 ++#define VEC_DAC_84_U13_ACTIVE_RISE_BITS 0x1fff0000 ++#define VEC_DAC_84_U13_ACTIVE_RISE_MSB 28 ++#define VEC_DAC_84_U13_ACTIVE_RISE_LSB 16 ++#define VEC_DAC_84_U13_ACTIVE_RISE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_84_U13_ACTIVE_FALL ++// Description : Horizontal blanking interval ++#define VEC_DAC_84_U13_ACTIVE_FALL_RESET 0x0000 ++#define VEC_DAC_84_U13_ACTIVE_FALL_BITS 0x00001fff ++#define VEC_DAC_84_U13_ACTIVE_FALL_MSB 12 ++#define VEC_DAC_84_U13_ACTIVE_FALL_LSB 0 ++#define VEC_DAC_84_U13_ACTIVE_FALL_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_88 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_88_OFFSET 0x00000088 ++#define VEC_DAC_88_BITS 0x1fff1fff ++#define VEC_DAC_88_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_88_U13_HALF_LINE_PERIOD ++// Description : Ratio of DAC clock to horizontal line rate, halved ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_RESET 0x0000 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_BITS 0x1fff0000 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_MSB 28 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_LSB 16 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_88_U13_HORZ_SYNC ++// Description : Width of horizontal sync pulses ++#define VEC_DAC_88_U13_HORZ_SYNC_RESET 0x0000 ++#define VEC_DAC_88_U13_HORZ_SYNC_BITS 0x00001fff ++#define VEC_DAC_88_U13_HORZ_SYNC_MSB 12 ++#define VEC_DAC_88_U13_HORZ_SYNC_LSB 0 ++#define VEC_DAC_88_U13_HORZ_SYNC_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_8C ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_8C_OFFSET 0x0000008c ++#define VEC_DAC_8C_BITS 0x1fff1fff ++#define VEC_DAC_8C_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_8C_U13_BURST_RISE ++// Description : Start of raised-cosine colour burst envelope ++#define VEC_DAC_8C_U13_BURST_RISE_RESET 0x0000 ++#define VEC_DAC_8C_U13_BURST_RISE_BITS 0x1fff0000 ++#define VEC_DAC_8C_U13_BURST_RISE_MSB 28 ++#define VEC_DAC_8C_U13_BURST_RISE_LSB 16 ++#define VEC_DAC_8C_U13_BURST_RISE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_8C_U13_BURST_FALL ++// Description : End of raised-cosine colour burst envelope ++#define VEC_DAC_8C_U13_BURST_FALL_RESET 0x0000 ++#define VEC_DAC_8C_U13_BURST_FALL_BITS 0x00001fff ++#define VEC_DAC_8C_U13_BURST_FALL_MSB 12 ++#define VEC_DAC_8C_U13_BURST_FALL_LSB 0 ++#define VEC_DAC_8C_U13_BURST_FALL_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_90 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_90_OFFSET 0x00000090 ++#define VEC_DAC_90_BITS 0x1fff3fff ++#define VEC_DAC_90_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_90_U13_VERT_EQ ++// Description : Width of vertical equalisation pulses (= half line minus ++// serration) ++#define VEC_DAC_90_U13_VERT_EQ_RESET 0x0000 ++#define VEC_DAC_90_U13_VERT_EQ_BITS 0x1fff0000 ++#define VEC_DAC_90_U13_VERT_EQ_MSB 28 ++#define VEC_DAC_90_U13_VERT_EQ_LSB 16 ++#define VEC_DAC_90_U13_VERT_EQ_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_90_U14_VERT_SYNC ++// Description : Width of vertical sync pulses ++#define VEC_DAC_90_U14_VERT_SYNC_RESET 0x0000 ++#define VEC_DAC_90_U14_VERT_SYNC_BITS 0x00003fff ++#define VEC_DAC_90_U14_VERT_SYNC_MSB 13 ++#define VEC_DAC_90_U14_VERT_SYNC_LSB 0 ++#define VEC_DAC_90_U14_VERT_SYNC_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_94 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_94_OFFSET 0x00000094 ++#define VEC_DAC_94_BITS 0x03ff03ff ++#define VEC_DAC_94_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_94_U10_PRE_EQ_BGN ++// Description : Half-lines, inclusive, relative to field datum, where vertical ++// pre-equalisation pulses start ++#define VEC_DAC_94_U10_PRE_EQ_BGN_RESET 0x000 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_BITS 0x03ff0000 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_MSB 25 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_LSB 16 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_94_U10_PRE_EQ_END ++// Description : Half-lines, inclusive, relative to field datum, where vertical ++// pre-equalisation pulses end ++#define VEC_DAC_94_U10_PRE_EQ_END_RESET 0x000 ++#define VEC_DAC_94_U10_PRE_EQ_END_BITS 0x000003ff ++#define VEC_DAC_94_U10_PRE_EQ_END_MSB 9 ++#define VEC_DAC_94_U10_PRE_EQ_END_LSB 0 ++#define VEC_DAC_94_U10_PRE_EQ_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_98 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_98_OFFSET 0x00000098 ++#define VEC_DAC_98_BITS 0x03ff03ff ++#define VEC_DAC_98_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_98_U10_FIELD_SYNC_BGN ++// Description : Half-lines containing vertical sync pulses (inclusive) ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_RESET 0x000 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_BITS 0x03ff0000 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_MSB 25 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_LSB 16 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_98_U10_FIELD_SYNC_END ++// Description : Half-lines containing vertical sync pulses (inclusive) ++#define VEC_DAC_98_U10_FIELD_SYNC_END_RESET 0x000 ++#define VEC_DAC_98_U10_FIELD_SYNC_END_BITS 0x000003ff ++#define VEC_DAC_98_U10_FIELD_SYNC_END_MSB 9 ++#define VEC_DAC_98_U10_FIELD_SYNC_END_LSB 0 ++#define VEC_DAC_98_U10_FIELD_SYNC_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_9C ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_9C_OFFSET 0x0000009c ++#define VEC_DAC_9C_BITS 0x03ff03ff ++#define VEC_DAC_9C_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_9C_U10_POST_EQ_BGN ++// Description : Half-lines containing vertical post-equalisation pulses ++#define VEC_DAC_9C_U10_POST_EQ_BGN_RESET 0x000 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_BITS 0x03ff0000 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_MSB 25 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_LSB 16 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_9C_U10_POST_EQ_END ++// Description : Half-lines containing vertical post-equalisation pulses ++#define VEC_DAC_9C_U10_POST_EQ_END_RESET 0x000 ++#define VEC_DAC_9C_U10_POST_EQ_END_BITS 0x000003ff ++#define VEC_DAC_9C_U10_POST_EQ_END_MSB 9 ++#define VEC_DAC_9C_U10_POST_EQ_END_LSB 0 ++#define VEC_DAC_9C_U10_POST_EQ_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_A0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_A0_OFFSET 0x000000a0 ++#define VEC_DAC_A0_BITS 0x03ff03ff ++#define VEC_DAC_A0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A0_U10_FLD1_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_RESET 0x000 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_MSB 25 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_LSB 16 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A0_U10_FLD1_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A0_U10_FLD1_BURST_END_RESET 0x000 ++#define VEC_DAC_A0_U10_FLD1_BURST_END_BITS 0x000003ff ++#define VEC_DAC_A0_U10_FLD1_BURST_END_MSB 9 ++#define VEC_DAC_A0_U10_FLD1_BURST_END_LSB 0 ++#define VEC_DAC_A0_U10_FLD1_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_A4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_A4_OFFSET 0x000000a4 ++#define VEC_DAC_A4_BITS 0x03ff03ff ++#define VEC_DAC_A4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A4_U10_FLD2_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_RESET 0x000 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_MSB 25 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_LSB 16 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A4_U10_FLD2_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A4_U10_FLD2_BURST_END_RESET 0x000 ++#define VEC_DAC_A4_U10_FLD2_BURST_END_BITS 0x000003ff ++#define VEC_DAC_A4_U10_FLD2_BURST_END_MSB 9 ++#define VEC_DAC_A4_U10_FLD2_BURST_END_LSB 0 ++#define VEC_DAC_A4_U10_FLD2_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_A8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_A8_OFFSET 0x000000a8 ++#define VEC_DAC_A8_BITS 0x03ff03ff ++#define VEC_DAC_A8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A8_U10_FLD3_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_RESET 0x000 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_MSB 25 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_LSB 16 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A8_U10_FLD3_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A8_U10_FLD3_BURST_END_RESET 0x000 ++#define VEC_DAC_A8_U10_FLD3_BURST_END_BITS 0x000003ff ++#define VEC_DAC_A8_U10_FLD3_BURST_END_MSB 9 ++#define VEC_DAC_A8_U10_FLD3_BURST_END_LSB 0 ++#define VEC_DAC_A8_U10_FLD3_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_AC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_AC_OFFSET 0x000000ac ++#define VEC_DAC_AC_BITS 0x03ff03ff ++#define VEC_DAC_AC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_AC_U10_FLD4_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_RESET 0x000 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_MSB 25 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_LSB 16 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_AC_U10_FLD4_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_AC_U10_FLD4_BURST_END_RESET 0x000 ++#define VEC_DAC_AC_U10_FLD4_BURST_END_BITS 0x000003ff ++#define VEC_DAC_AC_U10_FLD4_BURST_END_MSB 9 ++#define VEC_DAC_AC_U10_FLD4_BURST_END_LSB 0 ++#define VEC_DAC_AC_U10_FLD4_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_B0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_B0_OFFSET 0x000000b0 ++#define VEC_DAC_B0_BITS 0x03ff03ff ++#define VEC_DAC_B0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_RESET 0x000 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_BITS 0x03ff0000 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_MSB 25 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_LSB 16 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B0_U10_FLD24_FULL_LINE_END ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_RESET 0x000 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_BITS 0x000003ff ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_MSB 9 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_LSB 0 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_B4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_B4_OFFSET 0x000000b4 ++#define VEC_DAC_B4_BITS 0x03ff03ff ++#define VEC_DAC_B4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_RESET 0x000 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_BITS 0x03ff0000 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_MSB 25 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_LSB 16 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B4_U10_FLD13_FULL_LINE_END ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_RESET 0x000 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_BITS 0x000003ff ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_MSB 9 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_LSB 0 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_B8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_B8_OFFSET 0x000000b8 ++#define VEC_DAC_B8_BITS 0x03ff03ff ++#define VEC_DAC_B8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B8_U10_BOT_HALF_LINE ++// Description : Top and bottom visible half-lines in 1-based standard full ++// frame numbering, for interlaced modes. Set to zero to disable. ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_RESET 0x000 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_BITS 0x03ff0000 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_MSB 25 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_LSB 16 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B8_U10_TOP_HALF_LINE ++// Description : Top and bottom visible half-lines in 1-based standard full ++// frame numbering, for interlaced modes. Set to zero to disable. ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_RESET 0x000 ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_BITS 0x000003ff ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_MSB 9 ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_LSB 0 ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_BC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_BC_OFFSET 0x000000bc ++#define VEC_DAC_BC_BITS 0x07ff07ff ++#define VEC_DAC_BC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_BC_S11_PEDESTAL ++// Description : NTSC pedestal. For 7.5 IRE, this field is 1024 * 7.5/100. For ++// PAL, or Japanese NTSC, this field should be zero. ++#define VEC_DAC_BC_S11_PEDESTAL_RESET 0x000 ++#define VEC_DAC_BC_S11_PEDESTAL_BITS 0x07ff0000 ++#define VEC_DAC_BC_S11_PEDESTAL_MSB 26 ++#define VEC_DAC_BC_S11_PEDESTAL_LSB 16 ++#define VEC_DAC_BC_S11_PEDESTAL_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_BC_U11_HALF_LINES_PER_FIELD ++// Description : Mode = 625 PAL, Lines per field = 312.5, ++// u11_half_lines_per_field = 1+2*312 Mode = 525 NTSC, Lines per ++// field = 262.5, u11_half_lines_per_field = 1+2*262 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_RESET 0x000 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_BITS 0x000007ff ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_MSB 10 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_LSB 0 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_C0 ++// JTAG access : synchronous ++// Description : Synopsis DesignWare control ++#define VEC_DAC_C0_OFFSET 0x000000c0 ++#define VEC_DAC_C0_BITS 0x000fffff ++#define VEC_DAC_C0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_CABLE_ENCTR3 ++// Description : Synopsis test input ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_RESET 0x0 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_BITS 0x00080000 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_MSB 19 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_LSB 19 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_CABLE_CABLEOUT ++// Description : cable detect state ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_RESET 0x0 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_BITS 0x00070000 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_MSB 18 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_LSB 16 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_MUX_2 ++// Description : Select DAC channel 2 output ++#define VEC_DAC_C0_DWC_MUX_2_RESET 0x0 ++#define VEC_DAC_C0_DWC_MUX_2_BITS 0x0000c000 ++#define VEC_DAC_C0_DWC_MUX_2_MSB 15 ++#define VEC_DAC_C0_DWC_MUX_2_LSB 14 ++#define VEC_DAC_C0_DWC_MUX_2_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_MUX_1 ++// Description : Select DAC channel 1 output ++#define VEC_DAC_C0_DWC_MUX_1_RESET 0x0 ++#define VEC_DAC_C0_DWC_MUX_1_BITS 0x00003000 ++#define VEC_DAC_C0_DWC_MUX_1_MSB 13 ++#define VEC_DAC_C0_DWC_MUX_1_LSB 12 ++#define VEC_DAC_C0_DWC_MUX_1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_MUX_0 ++// Description : Select DAC channel 0 output ++#define VEC_DAC_C0_DWC_MUX_0_RESET 0x0 ++#define VEC_DAC_C0_DWC_MUX_0_BITS 0x00000c00 ++#define VEC_DAC_C0_DWC_MUX_0_MSB 11 ++#define VEC_DAC_C0_DWC_MUX_0_LSB 10 ++#define VEC_DAC_C0_DWC_MUX_0_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_TEST ++// Description : Fixed DAC command word ++#define VEC_DAC_C0_DWC_TEST_RESET 0x000 ++#define VEC_DAC_C0_DWC_TEST_BITS 0x000003ff ++#define VEC_DAC_C0_DWC_TEST_MSB 9 ++#define VEC_DAC_C0_DWC_TEST_LSB 0 ++#define VEC_DAC_C0_DWC_TEST_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_C4 ++// JTAG access : synchronous ++// Description : Synopsis DAC control ++#define VEC_DAC_C4_OFFSET 0x000000c4 ++#define VEC_DAC_C4_BITS 0x1fffffff ++#define VEC_DAC_C4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENCTR ++// Description : Always write3'b000 ++#define VEC_DAC_C4_ENCTR_RESET 0x0 ++#define VEC_DAC_C4_ENCTR_BITS 0x1c000000 ++#define VEC_DAC_C4_ENCTR_MSB 28 ++#define VEC_DAC_C4_ENCTR_LSB 26 ++#define VEC_DAC_C4_ENCTR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENSC ++// Description : Enable cable detect - write 3'b000 ++#define VEC_DAC_C4_ENSC_RESET 0x0 ++#define VEC_DAC_C4_ENSC_BITS 0x03800000 ++#define VEC_DAC_C4_ENSC_MSB 25 ++#define VEC_DAC_C4_ENSC_LSB 23 ++#define VEC_DAC_C4_ENSC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENDAC ++// Description : Enable DAC channel ++#define VEC_DAC_C4_ENDAC_RESET 0x0 ++#define VEC_DAC_C4_ENDAC_BITS 0x00700000 ++#define VEC_DAC_C4_ENDAC_MSB 22 ++#define VEC_DAC_C4_ENDAC_LSB 20 ++#define VEC_DAC_C4_ENDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENVBG ++// Description : Enable internal bandgap reference - write '1' ++#define VEC_DAC_C4_ENVBG_RESET 0x0 ++#define VEC_DAC_C4_ENVBG_BITS 0x00080000 ++#define VEC_DAC_C4_ENVBG_MSB 19 ++#define VEC_DAC_C4_ENVBG_LSB 19 ++#define VEC_DAC_C4_ENVBG_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENEXTREF ++// Description : Enable external reference - write '0' ++#define VEC_DAC_C4_ENEXTREF_RESET 0x0 ++#define VEC_DAC_C4_ENEXTREF_BITS 0x00040000 ++#define VEC_DAC_C4_ENEXTREF_MSB 18 ++#define VEC_DAC_C4_ENEXTREF_LSB 18 ++#define VEC_DAC_C4_ENEXTREF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_DAC2GC ++// Description : DAC channel 2 gain control - write 6'd63 ++#define VEC_DAC_C4_DAC2GC_RESET 0x00 ++#define VEC_DAC_C4_DAC2GC_BITS 0x0003f000 ++#define VEC_DAC_C4_DAC2GC_MSB 17 ++#define VEC_DAC_C4_DAC2GC_LSB 12 ++#define VEC_DAC_C4_DAC2GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_DAC1GC ++// Description : DAC channel 1 gain control - write 6'd63 ++#define VEC_DAC_C4_DAC1GC_RESET 0x00 ++#define VEC_DAC_C4_DAC1GC_BITS 0x00000fc0 ++#define VEC_DAC_C4_DAC1GC_MSB 11 ++#define VEC_DAC_C4_DAC1GC_LSB 6 ++#define VEC_DAC_C4_DAC1GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_DAC0GC ++// Description : DAC channel 0 gain control - write 6'd63 ++#define VEC_DAC_C4_DAC0GC_RESET 0x00 ++#define VEC_DAC_C4_DAC0GC_BITS 0x0000003f ++#define VEC_DAC_C4_DAC0GC_MSB 5 ++#define VEC_DAC_C4_DAC0GC_LSB 0 ++#define VEC_DAC_C4_DAC0GC_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_C8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_C8_OFFSET 0x000000c8 ++#define VEC_DAC_C8_BITS 0xffffffff ++#define VEC_DAC_C8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C8_U16_SCALE_SYNC ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_C8_U16_SCALE_SYNC_RESET 0x0000 ++#define VEC_DAC_C8_U16_SCALE_SYNC_BITS 0xffff0000 ++#define VEC_DAC_C8_U16_SCALE_SYNC_MSB 31 ++#define VEC_DAC_C8_U16_SCALE_SYNC_LSB 16 ++#define VEC_DAC_C8_U16_SCALE_SYNC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C8_U16_SCALE_LUMA ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_C8_U16_SCALE_LUMA_RESET 0x0000 ++#define VEC_DAC_C8_U16_SCALE_LUMA_BITS 0x0000ffff ++#define VEC_DAC_C8_U16_SCALE_LUMA_MSB 15 ++#define VEC_DAC_C8_U16_SCALE_LUMA_LSB 0 ++#define VEC_DAC_C8_U16_SCALE_LUMA_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_CC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_CC_OFFSET 0x000000cc ++#define VEC_DAC_CC_BITS 0xffffffff ++#define VEC_DAC_CC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_CC_S16_SCALE_BURST ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_CC_S16_SCALE_BURST_RESET 0x0000 ++#define VEC_DAC_CC_S16_SCALE_BURST_BITS 0xffff0000 ++#define VEC_DAC_CC_S16_SCALE_BURST_MSB 31 ++#define VEC_DAC_CC_S16_SCALE_BURST_LSB 16 ++#define VEC_DAC_CC_S16_SCALE_BURST_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_CC_S16_SCALE_CHROMA ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_CC_S16_SCALE_CHROMA_RESET 0x0000 ++#define VEC_DAC_CC_S16_SCALE_CHROMA_BITS 0x0000ffff ++#define VEC_DAC_CC_S16_SCALE_CHROMA_MSB 15 ++#define VEC_DAC_CC_S16_SCALE_CHROMA_LSB 0 ++#define VEC_DAC_CC_S16_SCALE_CHROMA_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_D0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_D0_OFFSET 0x000000d0 ++#define VEC_DAC_D0_BITS 0xffffffff ++#define VEC_DAC_D0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D0_S16_OFFSET_LUMA ++// Description : These offsets are applied to the chroma and luma channels ++// before the final MUX ++#define VEC_DAC_D0_S16_OFFSET_LUMA_RESET 0x0000 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_BITS 0xffff0000 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_MSB 31 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_LSB 16 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D0_S16_OFFSET_CHRO ++// Description : These offsets are applied to the chroma and luma channels ++// before the final MUX ++#define VEC_DAC_D0_S16_OFFSET_CHRO_RESET 0x0000 ++#define VEC_DAC_D0_S16_OFFSET_CHRO_BITS 0x0000ffff ++#define VEC_DAC_D0_S16_OFFSET_CHRO_MSB 15 ++#define VEC_DAC_D0_S16_OFFSET_CHRO_LSB 0 ++#define VEC_DAC_D0_S16_OFFSET_CHRO_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_D4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_D4_OFFSET 0x000000d4 ++#define VEC_DAC_D4_BITS 0xffffffff ++#define VEC_DAC_D4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D4_NCO_FREQ ++// Description : This 64-bit frequency command is applied to the phase ++// accumulator of the NCO (numerically controlled oscillator) ++// which generates the colour sub-carrier. This value is computed ++// as ratio of sub-carrier frequency to DAC clock multiplied by ++// 2^64. ++#define VEC_DAC_D4_NCO_FREQ_RESET 0x00000000 ++#define VEC_DAC_D4_NCO_FREQ_BITS 0xffffffff ++#define VEC_DAC_D4_NCO_FREQ_MSB 31 ++#define VEC_DAC_D4_NCO_FREQ_LSB 0 ++#define VEC_DAC_D4_NCO_FREQ_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_D8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_D8_OFFSET 0x000000d8 ++#define VEC_DAC_D8_BITS 0xffffffff ++#define VEC_DAC_D8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D8_NCO_FREQ ++// Description : This 64-bit frequency command is applied to the phase ++// accumulator of the NCO (numerically controlled oscillator) ++// which generates the colour sub-carrier. This value is computed ++// as ratio of sub-carrier frequency to DAC clock multiplied by ++// 2^64. ++#define VEC_DAC_D8_NCO_FREQ_RESET 0x00000000 ++#define VEC_DAC_D8_NCO_FREQ_BITS 0xffffffff ++#define VEC_DAC_D8_NCO_FREQ_MSB 31 ++#define VEC_DAC_D8_NCO_FREQ_LSB 0 ++#define VEC_DAC_D8_NCO_FREQ_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_DC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_DC_OFFSET 0x000000dc ++#define VEC_DAC_DC_BITS 0xffffffff ++#define VEC_DAC_DC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_DC_FIR_COEFF_CHROMA_0_6 ++// Description : FIR filter coefficients ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_RESET 0x0000 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_BITS 0xffff0000 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_MSB 31 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_LSB 16 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_DC_FIR_COEFF_LUMA_0_6 ++// Description : FIR filter coefficients ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_RESET 0x0000 ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_BITS 0x0000ffff ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_MSB 15 ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_LSB 0 ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_E0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_E0_OFFSET 0x000000e0 ++#define VEC_DAC_E0_BITS 0xffffffff ++#define VEC_DAC_E0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E0_FIR_COEFF_CHROMA_1_5 ++// Description : FIR filter coefficients ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_RESET 0x0000 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_BITS 0xffff0000 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_MSB 31 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_LSB 16 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E0_FIR_COEFF_LUMA_1_5 ++// Description : FIR filter coefficients ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_RESET 0x0000 ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_BITS 0x0000ffff ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_MSB 15 ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_LSB 0 ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_E4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_E4_OFFSET 0x000000e4 ++#define VEC_DAC_E4_BITS 0xffffffff ++#define VEC_DAC_E4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E4_FIR_COEFF_CHROMA_2_4 ++// Description : FIR filter coefficients ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_RESET 0x0000 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_BITS 0xffff0000 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_MSB 31 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_LSB 16 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E4_FIR_COEFF_LUMA_2_4 ++// Description : FIR filter coefficients ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_RESET 0x0000 ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_BITS 0x0000ffff ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_MSB 15 ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_LSB 0 ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_E8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_E8_OFFSET 0x000000e8 ++#define VEC_DAC_E8_BITS 0xffffffff ++#define VEC_DAC_E8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E8_FIR_COEFF_CHROMA_3 ++// Description : FIR filter coefficients ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_RESET 0x0000 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_BITS 0xffff0000 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_MSB 31 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_LSB 16 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E8_FIR_COEFF_LUMA_3 ++// Description : FIR filter coefficients ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_RESET 0x0000 ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_BITS 0x0000ffff ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_MSB 15 ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_LSB 0 ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_EC ++// JTAG access : synchronous ++// Description : Misc. control ++#define VEC_DAC_EC_OFFSET 0x000000ec ++#define VEC_DAC_EC_BITS 0x001fffff ++#define VEC_DAC_EC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_SLOW_CLOCK ++// Description : Doubles the raised-cosine rate ++#define VEC_DAC_EC_SLOW_CLOCK_RESET 0x0 ++#define VEC_DAC_EC_SLOW_CLOCK_BITS 0x00100000 ++#define VEC_DAC_EC_SLOW_CLOCK_MSB 20 ++#define VEC_DAC_EC_SLOW_CLOCK_LSB 20 ++#define VEC_DAC_EC_SLOW_CLOCK_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_FIR_RMINUS1 ++// Description : Select 1, 3, 5 or 7 FIR taps ++#define VEC_DAC_EC_FIR_RMINUS1_RESET 0x0 ++#define VEC_DAC_EC_FIR_RMINUS1_BITS 0x000c0000 ++#define VEC_DAC_EC_FIR_RMINUS1_MSB 19 ++#define VEC_DAC_EC_FIR_RMINUS1_LSB 18 ++#define VEC_DAC_EC_FIR_RMINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_VERT_FULL_NOT_HALF ++// Description : Disable half-line pulses during VBI ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_RESET 0x0 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_BITS 0x00020000 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_MSB 17 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_LSB 17 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_SEQ_EN ++// Description : Enable NCO reset ++#define VEC_DAC_EC_SEQ_EN_RESET 0x0 ++#define VEC_DAC_EC_SEQ_EN_BITS 0x00010000 ++#define VEC_DAC_EC_SEQ_EN_MSB 16 ++#define VEC_DAC_EC_SEQ_EN_LSB 16 ++#define VEC_DAC_EC_SEQ_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_U2_FLD_MASK ++// Description : Field sequence ++#define VEC_DAC_EC_U2_FLD_MASK_RESET 0x0 ++#define VEC_DAC_EC_U2_FLD_MASK_BITS 0x0000c000 ++#define VEC_DAC_EC_U2_FLD_MASK_MSB 15 ++#define VEC_DAC_EC_U2_FLD_MASK_LSB 14 ++#define VEC_DAC_EC_U2_FLD_MASK_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_U4_SEQ_MASK ++// Description : NCO reset sequence ++#define VEC_DAC_EC_U4_SEQ_MASK_RESET 0x0 ++#define VEC_DAC_EC_U4_SEQ_MASK_BITS 0x00003c00 ++#define VEC_DAC_EC_U4_SEQ_MASK_MSB 13 ++#define VEC_DAC_EC_U4_SEQ_MASK_LSB 10 ++#define VEC_DAC_EC_U4_SEQ_MASK_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_INTERP_RATE_MINUS1 ++// Description : Interpolation rate 2<=R<=16 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_RESET 0x0 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_BITS 0x000003c0 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_MSB 9 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_LSB 6 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_INTERP_SHIFT_MINUS1 ++// Description : Power-of-2 scaling after interpolation ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_RESET 0x0 ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_BITS 0x0000003c ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_MSB 5 ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_LSB 2 ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1 ++// Description : Interlaced / progressive ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_RESET 0x0 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_BITS 0x00000002 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_MSB 1 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_LSB 1 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_PAL_EN ++// Description : Enable phase alternate line (PAL) mode ++#define VEC_DAC_EC_PAL_EN_RESET 0x0 ++#define VEC_DAC_EC_PAL_EN_BITS 0x00000001 ++#define VEC_DAC_EC_PAL_EN_MSB 0 ++#define VEC_DAC_EC_PAL_EN_LSB 0 ++#define VEC_DAC_EC_PAL_EN_ACCESS "RW" ++// ============================================================================= ++#endif // VEC_REGS_DEFINED diff --git a/target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch b/target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch new file mode 100644 index 0000000000..cf0b02c64b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch @@ -0,0 +1,75 @@ +From 3a419974ba02d32795a5ecfaf3c020f23173b6a1 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 14 Feb 2023 20:58:59 +0000 +Subject: [PATCH] v4l2: Add pisp compression format support to v4l2 + +Signed-off-by: Naushir Patuck +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 12 ++++++++---- + include/uapi/linux/media-bus-format.h | 14 ++++++++++++++ + include/uapi/linux/videodev2.h | 12 ++++++++---- + 3 files changed, 30 insertions(+), 8 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1507,10 +1507,14 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break; + case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break; + case V4L2_PIX_FMT_RPI_BE: descr = "PiSP Opaque Format"; break; +- case V4L2_PIX_FMT_PISP_COMP_RGGB: +- case V4L2_PIX_FMT_PISP_COMP_GRBG: +- case V4L2_PIX_FMT_PISP_COMP_GBRG: +- case V4L2_PIX_FMT_PISP_COMP_BGGR: descr = "PiSP Bayer Compressed Format"; break; ++ case V4L2_PIX_FMT_PISP_COMP1_RGGB: ++ case V4L2_PIX_FMT_PISP_COMP1_GRBG: ++ case V4L2_PIX_FMT_PISP_COMP1_GBRG: ++ case V4L2_PIX_FMT_PISP_COMP1_BGGR: descr = "PiSP Bayer Comp 1"; break; ++ case V4L2_PIX_FMT_PISP_COMP2_RGGB: ++ case V4L2_PIX_FMT_PISP_COMP2_GRBG: ++ case V4L2_PIX_FMT_PISP_COMP2_GBRG: ++ case V4L2_PIX_FMT_PISP_COMP2_BGGR: descr = "PiSP Bayer Comp 2"; break; + default: + if (fmt->description[0]) + return; +--- a/include/uapi/linux/media-bus-format.h ++++ b/include/uapi/linux/media-bus-format.h +@@ -175,4 +175,18 @@ + /* Sensor ancillary metadata formats - next is 0x7002 */ + #define MEDIA_BUS_FMT_SENSOR_DATA 0x7002 + ++/* PiSP Formats */ ++#define MEDIA_BUS_FMT_PISP_COMP1_RGGB 0x8001 ++#define MEDIA_BUS_FMT_PISP_COMP1_GRBG 0x8002 ++#define MEDIA_BUS_FMT_PISP_COMP1_GBRG 0x8003 ++#define MEDIA_BUS_FMT_PISP_COMP1_BGGR 0x8004 ++#define MEDIA_BUS_FMT_PISP_COMP2_RGGB 0x8005 ++#define MEDIA_BUS_FMT_PISP_COMP2_GRBG 0x8006 ++#define MEDIA_BUS_FMT_PISP_COMP2_GBRG 0x8007 ++#define MEDIA_BUS_FMT_PISP_COMP2_BGGR 0x8008 ++ ++#define MEDIA_BUS_FMT_PISP_FE_CONFIG 0x8100 ++#define MEDIA_BUS_FMT_PISP_FE_STATS 0x8101 ++#define MEDIA_BUS_FMT_PISP_BE_CONFIG 0x8200 ++ + #endif /* __LINUX_MEDIA_BUS_FORMAT_H */ +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -795,10 +795,14 @@ struct v4l2_pix_format { + + /* The pixel format for all our buffers (the precise format is found in the config buffer). */ + #define V4L2_PIX_FMT_RPI_BE v4l2_fourcc('R', 'P', 'B', 'P') +-#define V4L2_PIX_FMT_PISP_COMP_RGGB v4l2_fourcc('P', 'C', 'R', 'G') +-#define V4L2_PIX_FMT_PISP_COMP_GRBG v4l2_fourcc('P', 'C', 'G', 'R') +-#define V4L2_PIX_FMT_PISP_COMP_GBRG v4l2_fourcc('P', 'C', 'G', 'B') +-#define V4L2_PIX_FMT_PISP_COMP_BGGR v4l2_fourcc('P', 'C', 'B', 'G') ++#define V4L2_PIX_FMT_PISP_COMP1_RGGB v4l2_fourcc('P', 'C', '1', 'R') ++#define V4L2_PIX_FMT_PISP_COMP1_GRBG v4l2_fourcc('P', 'C', '1', 'G') ++#define V4L2_PIX_FMT_PISP_COMP1_GBRG v4l2_fourcc('P', 'C', '1', 'g') ++#define V4L2_PIX_FMT_PISP_COMP1_BGGR v4l2_fourcc('P', 'C', '1', 'B') ++#define V4L2_PIX_FMT_PISP_COMP2_RGGB v4l2_fourcc('P', 'C', '2', 'R') ++#define V4L2_PIX_FMT_PISP_COMP2_GRBG v4l2_fourcc('P', 'C', '2', 'G') ++#define V4L2_PIX_FMT_PISP_COMP2_GBRG v4l2_fourcc('P', 'C', '2', 'g') ++#define V4L2_PIX_FMT_PISP_COMP2_BGGR v4l2_fourcc('P', 'C', '2', 'B') + + /* SDR formats - used only for Software Defined Radio devices */ + #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch b/target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch new file mode 100644 index 0000000000..038633b74e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch @@ -0,0 +1,4527 @@ +From 8a31623de7f034f6521b348e9a510e78a6e7e493 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 14 Feb 2023 17:30:12 +0000 +Subject: [PATCH] media: rp1: Add CFE (Camera Front End) support + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/Kconfig | 1 + + drivers/media/platform/raspberrypi/Makefile | 1 + + .../platform/raspberrypi/rp1_cfe/Kconfig | 14 + + .../platform/raspberrypi/rp1_cfe/Makefile | 6 + + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 2186 +++++++++++++++++ + .../media/platform/raspberrypi/rp1_cfe/cfe.h | 40 + + .../platform/raspberrypi/rp1_cfe/cfe_fmts.h | 294 +++ + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 446 ++++ + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 75 + + .../media/platform/raspberrypi/rp1_cfe/dphy.c | 177 ++ + .../media/platform/raspberrypi/rp1_cfe/dphy.h | 26 + + .../raspberrypi/rp1_cfe/pisp_common.h | 69 + + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 563 +++++ + .../platform/raspberrypi/rp1_cfe/pisp_fe.h | 53 + + .../raspberrypi/rp1_cfe/pisp_fe_config.h | 272 ++ + .../raspberrypi/rp1_cfe/pisp_statistics.h | 62 + + .../platform/raspberrypi/rp1_cfe/pisp_types.h | 144 ++ + 17 files changed, 4429 insertions(+) + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/Kconfig + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/Makefile + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/csi2.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/csi2.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/dphy.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/dphy.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h + +--- a/drivers/media/platform/raspberrypi/Kconfig ++++ b/drivers/media/platform/raspberrypi/Kconfig +@@ -3,3 +3,4 @@ + comment "Raspberry Pi media platform drivers" + + source "drivers/media/platform/raspberrypi/pisp_be/Kconfig" ++source "drivers/media/platform/raspberrypi/rp1_cfe/Kconfig" +--- a/drivers/media/platform/raspberrypi/Makefile ++++ b/drivers/media/platform/raspberrypi/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + + obj-y += pisp_be/ ++obj-y += rp1_cfe/ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/Kconfig +@@ -0,0 +1,14 @@ ++# RP1 V4L2 camera support ++ ++config VIDEO_RP1_CFE ++ tristate "RP1 Camera Frond End (CFE) video capture driver" ++ 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 RP1 Camera Front End. ++ ++ To compile this driver as a module, choose M here. The module will be ++ called rp1-cfe. +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for RP1 Camera Front End driver ++# ++rp1-cfe-objs := cfe.o csi2.o pisp_fe.o dphy.o ++obj-$(CONFIG_VIDEO_RP1_CFE) += rp1-cfe.o +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -0,0 +1,2186 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RP1 Camera Front End Driver ++ * ++ * Copyright (C) 2021-2022 - Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cfe.h" ++#include "cfe_fmts.h" ++#include "csi2.h" ++#include "pisp_fe.h" ++#include "pisp_fe_config.h" ++#include "pisp_statistics.h" ++ ++#define CFE_MODULE_NAME "rp1-cfe" ++#define CFE_VERSION "1.0" ++ ++bool cfe_debug_irq; ++ ++#define cfe_dbg_irq(fmt, arg...) \ ++ do { \ ++ if (cfe_debug_irq) \ ++ dev_dbg(&cfe->pdev->dev, fmt, ##arg); \ ++ } while (0) ++#define cfe_dbg(fmt, arg...) dev_dbg(&cfe->pdev->dev, fmt, ##arg) ++#define cfe_info(fmt, arg...) dev_info(&cfe->pdev->dev, fmt, ##arg) ++#define cfe_err(fmt, arg...) dev_err(&cfe->pdev->dev, fmt, ##arg) ++ ++/* MIPICFG registers */ ++#define MIPICFG_CFG 0x004 ++#define MIPICFG_INTR 0x028 ++#define MIPICFG_INTE 0x02c ++#define MIPICFG_INTF 0x030 ++#define MIPICFG_INTS 0x034 ++ ++#define MIPICFG_CFG_SEL_CSI BIT(0) ++ ++#define MIPICFG_INT_CSI_DMA BIT(0) ++#define MIPICFG_INT_CSI_HOST BIT(2) ++#define MIPICFG_INT_PISP_FE BIT(4) ++ ++#define BPL_ALIGNMENT 16 ++#define MAX_BYTESPERLINE 0xffffff00 ++#define MAX_BUFFER_SIZE 0xffffff00 ++/* ++ * Max width is therefore determined by the max stride divided by the number of ++ * bits per pixel. ++ * ++ * However, to avoid overflow issues let's use a 16k maximum. This lets us ++ * calculate 16k * 16k * 4 with 32bits. If we need higher maximums, a careful ++ * review and adjustment of the code is needed so that it will deal with ++ * overflows correctly. ++ */ ++#define MAX_WIDTH 16384 ++#define MAX_HEIGHT MAX_WIDTH ++/* Define a nominal minimum image size */ ++#define MIN_WIDTH 16 ++#define MIN_HEIGHT 16 ++/* Default size of the embedded buffer */ ++#define DEFAULT_EMBEDDED_SIZE 8192 ++ ++const struct v4l2_mbus_framefmt cfe_default_format = { ++ .width = 640, ++ .height = 480, ++ .code = MEDIA_BUS_FMT_SRGGB10_1X10, ++ .field = V4L2_FIELD_NONE, ++ .colorspace = V4L2_COLORSPACE_RAW, ++ .ycbcr_enc = V4L2_YCBCR_ENC_601, ++ .quantization = V4L2_QUANTIZATION_FULL_RANGE, ++ .xfer_func = V4L2_XFER_FUNC_NONE, ++}; ++ ++const struct v4l2_mbus_framefmt cfe_default_meta_format = { ++ .width = 8192, ++ .height = 1, ++ .code = MEDIA_BUS_FMT_SENSOR_DATA, ++}; ++ ++enum node_ids { ++ /* CSI2 HW output nodes first. */ ++ CSI2_CH0, ++ CSI2_CH1_EMBEDDED, ++ CSI2_CH2, ++ CSI2_CH3, ++ /* FE only nodes from here on. */ ++ FE_OUT0, ++ FE_OUT1, ++ FE_STATS, ++ FE_CONFIG, ++ NUM_NODES ++}; ++ ++struct node_description { ++ unsigned int id; ++ const char *name; ++ enum v4l2_buf_type buf_type; ++ unsigned int cap; ++ unsigned int pad_flags; ++ unsigned int link_pad; ++}; ++ ++/* Must match the ordering of enum ids */ ++static const struct node_description node_desc[NUM_NODES] = { ++ [CSI2_CH0] = { ++ .name = "csi2_ch0", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 0 ++ }, ++ /* This node is assigned for the embedded data channel! */ ++ [CSI2_CH1_EMBEDDED] = { ++ .name = "embedded", ++ .buf_type = V4L2_BUF_TYPE_META_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 1 ++ }, ++ [CSI2_CH2] = { ++ .name = "csi2_ch2", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 2 ++ }, ++ [CSI2_CH3] = { ++ .name = "csi2_ch3", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 3 ++ }, ++ [FE_OUT0] = { ++ .name = "fe_image0", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_OUTPUT0_PAD ++ }, ++ [FE_OUT1] = { ++ .name = "fe_image1", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_OUTPUT1_PAD ++ }, ++ [FE_STATS] = { ++ .name = "fe_stats", ++ .buf_type = V4L2_BUF_TYPE_META_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_STATS_PAD ++ }, ++ [FE_CONFIG] = { ++ .name = "fe_config", ++ .buf_type = V4L2_BUF_TYPE_META_OUTPUT, ++ .cap = V4L2_CAP_META_OUTPUT, ++ .pad_flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_CONFIG_PAD ++ }, ++}; ++ ++#define is_fe_node(node) (((node)->id) >= FE_OUT0) ++#define is_csi2_node(node) (!is_fe_node(node)) ++#define is_image_output_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ++#define is_meta_output_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE) ++#define is_meta_input_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT) ++#define is_meta_node(node) (is_meta_output_node(node) || is_meta_input_node(node)) ++ ++/* To track state across all nodes. */ ++#define NUM_STATES 5 ++#define NODE_REGISTERED BIT(0) ++#define NODE_ENABLED BIT(1) ++#define NODE_STREAMING BIT(2) ++#define FS_INT BIT(3) ++#define FE_INT BIT(4) ++ ++struct cfe_buffer { ++ struct vb2_v4l2_buffer vb; ++ struct list_head list; ++}; ++ ++struct cfe_config_buffer { ++ struct cfe_buffer buf; ++ struct pisp_fe_config config; ++}; ++ ++static inline struct cfe_buffer *to_cfe_buffer(struct vb2_buffer *vb) ++{ ++ return container_of(vb, struct cfe_buffer, vb.vb2_buf); ++} ++ ++static inline ++struct cfe_config_buffer *to_cfe_config_buffer(struct cfe_buffer *buf) ++{ ++ return container_of(buf, struct cfe_config_buffer, buf); ++} ++ ++struct cfe_node { ++ unsigned int id; ++ /* Pointer pointing to current v4l2_buffer */ ++ struct cfe_buffer *cur_frm; ++ /* Pointer pointing to next v4l2_buffer */ ++ struct cfe_buffer *next_frm; ++ /* Used to store current pixel format */ ++ struct v4l2_format fmt; ++ /* Buffer queue used in video-buf */ ++ struct vb2_queue buffer_queue; ++ /* Queue of filled frames */ ++ struct list_head dma_queue; ++ /* lock used to access this structure */ ++ struct mutex lock; ++ /* Identifies video device for this channel */ ++ struct video_device video_dev; ++ /* Pointer to the parent handle */ ++ struct cfe_device *cfe; ++ struct media_pad pad; ++}; ++ ++struct cfe_device { ++ struct dentry *debugfs; ++ struct kref kref; ++ ++ /* V4l2 specific parameters */ ++ struct v4l2_async_subdev asd; ++ ++ /* peripheral base address */ ++ void __iomem *mipi_cfg_base; ++ ++ struct clk *clk; ++ ++ /* V4l2 device */ ++ struct v4l2_device v4l2_dev; ++ struct media_device mdev; ++ struct media_pipeline pipe; ++ ++ /* IRQ lock for node state and DMA queues */ ++ spinlock_t state_lock; ++ bool job_ready; ++ bool job_queued; ++ ++ /* parent device */ ++ struct platform_device *pdev; ++ /* subdevice async Notifier */ ++ struct v4l2_async_notifier notifier; ++ ++ /* ptr to sub device */ ++ struct v4l2_subdev *sensor; ++ ++ struct cfe_node node[NUM_NODES]; ++ DECLARE_BITMAP(node_flags, NUM_STATES * NUM_NODES); ++ ++ struct csi2_device csi2; ++ struct pisp_fe_device fe; ++ ++ bool sensor_embedded_data; ++ int fe_csi2_channel; ++ ++ unsigned int sequence; ++ u64 ts; ++}; ++ ++static inline bool is_fe_enabled(struct cfe_device *cfe) ++{ ++ return cfe->fe_csi2_channel != -1; ++} ++ ++static inline struct cfe_device *to_cfe_device(struct v4l2_device *v4l2_dev) ++{ ++ return container_of(v4l2_dev, struct cfe_device, v4l2_dev); ++} ++ ++static inline u32 cfg_reg_read(struct cfe_device *cfe, u32 offset) ++{ ++ return readl(cfe->mipi_cfg_base + offset); ++} ++ ++static inline void cfg_reg_write(struct cfe_device *cfe, u32 offset, u32 val) ++{ ++ writel(val, cfe->mipi_cfg_base + offset); ++} ++ ++static bool check_state(struct cfe_device *cfe, unsigned long state, ++ unsigned int node_id) ++{ ++ unsigned long bit; ++ ++ for_each_set_bit(bit, &state, sizeof(state)) { ++ if (!test_bit(bit + (node_id * NUM_STATES), cfe->node_flags)) ++ return false; ++ } ++ return true; ++} ++ ++static void set_state(struct cfe_device *cfe, unsigned long state, ++ unsigned int node_id) ++{ ++ unsigned long bit; ++ ++ for_each_set_bit(bit, &state, sizeof(state)) ++ set_bit(bit + (node_id * NUM_STATES), cfe->node_flags); ++} ++ ++static void clear_state(struct cfe_device *cfe, unsigned long state, ++ unsigned int node_id) ++{ ++ unsigned long bit; ++ ++ for_each_set_bit(bit, &state, sizeof(state)) ++ clear_bit(bit + (node_id * NUM_STATES), cfe->node_flags); ++} ++ ++static bool test_any_node(struct cfe_device *cfe, unsigned long cond) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (check_state(cfe, cond, i)) ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool test_all_nodes(struct cfe_device *cfe, unsigned long precond, ++ unsigned long cond) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (check_state(cfe, precond, i)) { ++ if (!check_state(cfe, cond, i)) ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static void clear_all_nodes(struct cfe_device *cfe, unsigned long precond, ++ unsigned long state) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (check_state(cfe, precond, i)) ++ clear_state(cfe, state, i); ++ } ++} ++ ++static int mipi_cfg_regs_show(struct seq_file *s, void *data) ++{ ++ struct cfe_device *cfe = s->private; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(&cfe->pdev->dev); ++ if (ret) ++ return ret; ++ ++#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", cfg_reg_read(cfe, reg)) ++ DUMP(MIPICFG_CFG); ++ DUMP(MIPICFG_INTR); ++ DUMP(MIPICFG_INTE); ++ DUMP(MIPICFG_INTF); ++ DUMP(MIPICFG_INTS); ++#undef DUMP ++ ++ pm_runtime_put(&cfe->pdev->dev); ++ ++ return 0; ++} ++ ++static int format_show(struct seq_file *s, void *data) ++{ ++ struct cfe_device *cfe = s->private; ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ unsigned long sb, state = 0; ++ ++ for (sb = 0; sb < NUM_STATES; sb++) { ++ if (check_state(cfe, BIT(sb), i)) ++ state |= BIT(sb); ++ } ++ ++ seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i, ++ node_desc[i].name, state); ++ ++ if (is_image_output_node(node)) ++ seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n" ++ "resolution: %ux%u\nbpl: %u\nsize: %u\n", ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat), ++ node->fmt.fmt.pix.pixelformat, ++ node->fmt.fmt.pix.width, ++ node->fmt.fmt.pix.height, ++ node->fmt.fmt.pix.bytesperline, ++ node->fmt.fmt.pix.sizeimage); ++ else ++ seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\nsize: %u\n", ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat), ++ node->fmt.fmt.meta.dataformat, ++ node->fmt.fmt.meta.buffersize); ++ } ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(mipi_cfg_regs); ++DEFINE_SHOW_ATTRIBUTE(format); ++ ++/* Format setup functions */ ++const struct cfe_fmt *find_format_by_code(u32 code) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(formats); i++) { ++ if (formats[i].code == code) ++ return &formats[i]; ++ } ++ ++ return NULL; ++} ++ ++static const struct cfe_fmt *find_format_by_pix(u32 pixelformat) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(formats); i++) { ++ if (formats[i].fourcc == pixelformat) ++ return &formats[i]; ++ } ++ ++ return NULL; ++} ++ ++static int cfe_calc_format_size_bpl(struct cfe_device *cfe, ++ const struct cfe_fmt *fmt, ++ struct v4l2_format *f) ++{ ++ unsigned int min_bytesperline; ++ ++ v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 2, ++ &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0, 0); ++ ++ min_bytesperline = ++ ALIGN((f->fmt.pix.width * fmt->depth) >> 3, BPL_ALIGNMENT); ++ ++ if (f->fmt.pix.bytesperline > min_bytesperline && ++ f->fmt.pix.bytesperline <= MAX_BYTESPERLINE) ++ f->fmt.pix.bytesperline = ++ ALIGN(f->fmt.pix.bytesperline, BPL_ALIGNMENT); ++ else ++ f->fmt.pix.bytesperline = min_bytesperline; ++ ++ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; ++ ++ cfe_dbg("%s: " V4L2_FOURCC_CONV " size: %ux%u bpl:%u img_size:%u\n", ++ __func__, V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat), ++ f->fmt.pix.width, f->fmt.pix.height, ++ f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); ++ ++ return 0; ++} ++ ++static void cfe_schedule_next_csi2_job(struct cfe_device *cfe) ++{ ++ struct cfe_buffer *buf; ++ unsigned int i; ++ dma_addr_t addr; ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ unsigned int stride, size; ++ ++ if (!check_state(cfe, NODE_STREAMING, i)) ++ continue; ++ ++ buf = list_first_entry(&node->dma_queue, struct cfe_buffer, ++ list); ++ node->next_frm = buf; ++ list_del(&buf->list); ++ ++ cfe_dbg("%s: [%s] buffer:%p\n", ++ __func__, node_desc[node->id].name, &buf->vb.vb2_buf); ++ ++ if (is_meta_node(node)) { ++ size = node->fmt.fmt.meta.buffersize; ++ stride = 0; ++ } else { ++ size = node->fmt.fmt.pix.sizeimage; ++ stride = node->fmt.fmt.pix.bytesperline; ++ } ++ ++ addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); ++ csi2_set_buffer(&cfe->csi2, node->id, addr, stride, size); ++ } ++} ++ ++static void cfe_schedule_next_pisp_job(struct cfe_device *cfe) ++{ ++ struct vb2_buffer *vb2_bufs[FE_NUM_PADS] = { 0 }; ++ struct cfe_config_buffer *config_buf; ++ struct cfe_buffer *buf; ++ unsigned int i; ++ ++ for (i = CSI2_NUM_CHANNELS; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (!check_state(cfe, NODE_STREAMING, i)) ++ continue; ++ ++ buf = list_first_entry(&node->dma_queue, struct cfe_buffer, ++ list); ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); ++ ++ node->next_frm = buf; ++ vb2_bufs[node_desc[i].link_pad] = &buf->vb.vb2_buf; ++ list_del(&buf->list); ++ } ++ ++ config_buf = to_cfe_config_buffer(cfe->node[FE_CONFIG].next_frm); ++ pisp_fe_submit_job(&cfe->fe, vb2_bufs, &config_buf->config); ++} ++ ++static bool cfe_check_job_ready(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (!check_state(cfe, NODE_ENABLED, i)) ++ continue; ++ ++ if (list_empty(&node->dma_queue)) { ++ cfe_dbg_irq("%s: [%s] has no buffer, unable to schedule job\n", ++ __func__, node_desc[i].name); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static void cfe_prepare_next_job(struct cfe_device *cfe) ++{ ++ cfe->job_queued = true; ++ cfe_schedule_next_csi2_job(cfe); ++ if (is_fe_enabled(cfe)) ++ cfe_schedule_next_pisp_job(cfe); ++ ++ /* Flag if another job is ready after this. */ ++ cfe->job_ready = cfe_check_job_ready(cfe); ++ ++ cfe_dbg_irq("%s: end with scheduled job\n", __func__); ++} ++ ++static void cfe_process_buffer_complete(struct cfe_node *node, ++ unsigned int sequence) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, ++ &node->cur_frm->vb.vb2_buf); ++ ++ node->cur_frm->vb.sequence = sequence; ++ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); ++} ++ ++static void cfe_queue_event_sof(struct cfe_node *node) ++{ ++ struct v4l2_event event = { ++ .type = V4L2_EVENT_FRAME_SYNC, ++ .u.frame_sync.frame_sequence = node->cfe->sequence, ++ }; ++ ++ v4l2_event_queue(&node->video_dev, &event); ++} ++ ++static void cfe_sof_isr_handler(struct cfe_node *node) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); ++ ++ node->cur_frm = node->next_frm; ++ node->next_frm = NULL; ++ ++ /* ++ * If this is the first node to see a frame start, sample the ++ * timestamp to use for all frames across all channels. ++ */ ++ if (!test_any_node(cfe, NODE_STREAMING | FS_INT)) ++ cfe->ts = ktime_get_ns(); ++ ++ set_state(cfe, FS_INT, node->id); ++ ++ /* If all nodes have seen a frame start, we can queue another job. */ ++ if (test_all_nodes(cfe, NODE_STREAMING, FS_INT)) ++ cfe->job_queued = false; ++ ++ if (node->cur_frm) ++ node->cur_frm->vb.vb2_buf.timestamp = cfe->ts; ++ ++ if (is_image_output_node(node)) ++ cfe_queue_event_sof(node); ++} ++ ++static void cfe_eof_isr_handler(struct cfe_node *node) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); ++ ++ if (node->cur_frm) ++ cfe_process_buffer_complete(node, cfe->sequence); ++ ++ node->cur_frm = NULL; ++ set_state(cfe, FE_INT, node->id); ++ ++ /* ++ * If all nodes have seen a frame end, we can increment ++ * the sequence counter now. ++ */ ++ if (test_all_nodes(cfe, NODE_STREAMING, FE_INT)) { ++ cfe->sequence++; ++ clear_all_nodes(cfe, NODE_STREAMING, FE_INT | FS_INT); ++ } ++} ++ ++static irqreturn_t cfe_isr(int irq, void *dev) ++{ ++ struct cfe_device *cfe = dev; ++ unsigned int i; ++ bool sof[NUM_NODES] = {0}, eof[NUM_NODES] = {0}, lci[NUM_NODES] = {0}; ++ u32 sts; ++ ++ sts = cfg_reg_read(cfe, MIPICFG_INTS); ++ ++ if (sts & MIPICFG_INT_CSI_DMA) ++ csi2_isr(&cfe->csi2, sof, eof, lci); ++ ++ if (sts & MIPICFG_INT_PISP_FE) ++ pisp_fe_isr(&cfe->fe, sof + CSI2_NUM_CHANNELS, ++ eof + CSI2_NUM_CHANNELS); ++ ++ spin_lock(&cfe->state_lock); ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ /* ++ * The check_state(NODE_STREAMING) is to ensure we do not loop ++ * over the CSI2_CHx nodes when the FE is active since they ++ * generate interrupts even though the node is not streaming. ++ */ ++ if (!check_state(cfe, NODE_STREAMING, i) || ++ !(sof[i] || eof[i] || lci[i])) ++ continue; ++ ++ /* ++ * There are 3 cases where we could get FS + FE_ACK at ++ * the same time: ++ * 1) FE of the current frame, and FS of the next frame. ++ * 2) FS + FE of the same frame. ++ * 3) FE of the current frame, and FS + FE of the next ++ * frame. To handle this, see the sof handler below. ++ * ++ * (1) is handled implicitly by the ordering of the FE and FS ++ * handlers below. ++ */ ++ if (eof[i]) { ++ /* ++ * The condition below tests for (2). Run the FS handler ++ * first before the FE handler, both for the current ++ * frame. ++ */ ++ if (sof[i] && !check_state(cfe, FS_INT, i)) { ++ cfe_sof_isr_handler(node); ++ sof[i] = false; ++ } ++ ++ cfe_eof_isr_handler(node); ++ } ++ ++ if (sof[i]) { ++ /* ++ * The condition below tests for (3). In such cases, we ++ * come in here with FS flag set in the node state from ++ * the previous frame since it only gets cleared in ++ * eof_isr_handler(). Handle the FE for the previous ++ * frame first before the FS handler for the current ++ * frame. ++ */ ++ if (check_state(cfe, FS_INT, node->id)) { ++ cfe_dbg("%s: [%s] Handling missing previous FE interrupt\n", ++ __func__, node_desc[node->id].name); ++ cfe_eof_isr_handler(node); ++ } ++ ++ cfe_sof_isr_handler(node); ++ } ++ ++ if (!cfe->job_queued && cfe->job_ready) ++ cfe_prepare_next_job(cfe); ++ } ++ ++ spin_unlock(&cfe->state_lock); ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Stream helpers ++ */ ++ ++static void cfe_start_channel(struct cfe_node *node) ++{ ++ struct cfe_device *cfe = node->cfe; ++ struct v4l2_subdev_state *state; ++ struct v4l2_mbus_framefmt *source_fmt; ++ const struct cfe_fmt *fmt; ++ unsigned long flags; ++ unsigned int width = 0, height = 0; ++ bool start_fe = is_fe_enabled(cfe) && ++ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (start_fe || is_image_output_node(node)) { ++ width = node->fmt.fmt.pix.width; ++ height = node->fmt.fmt.pix.height; ++ } ++ ++ state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd); ++ ++ if (start_fe) { ++ WARN_ON(!is_fe_enabled(cfe)); ++ cfe_dbg("%s: %s using csi2 channel %d\n", ++ __func__, node_desc[FE_OUT0].name, ++ cfe->fe_csi2_channel); ++ ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, cfe->fe_csi2_channel); ++ fmt = find_format_by_code(source_fmt->code); ++ ++ /* ++ * Start the associated CSI2 Channel as well. ++ * ++ * Must write to the ADDR register to latch the ctrl values ++ * even if we are connected to the front end. Once running, ++ * this is handled by the CSI2 AUTO_ARM mode. ++ */ ++ csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel, ++ fmt->csi_dt, CSI2_MODE_FE_STREAMING, ++ true, false, width, height); ++ csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1); ++ pisp_fe_start(&cfe->fe); ++ } ++ ++ if (is_csi2_node(node)) { ++ u32 mode = CSI2_MODE_NORMAL; ++ ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, ++ node_desc[node->id].link_pad - CSI2_NUM_CHANNELS); ++ fmt = find_format_by_code(source_fmt->code); ++ ++ if (is_image_output_node(node)) { ++ if (node->fmt.fmt.pix.pixelformat == ++ fmt->remap[CFE_REMAP_16BIT]) ++ mode = CSI2_MODE_REMAP; ++ else if (node->fmt.fmt.pix.pixelformat == ++ fmt->remap[CFE_REMAP_COMPRESSED]) { ++ mode = CSI2_MODE_COMPRESSED; ++ csi2_set_compression(&cfe->csi2, node->id, ++ CSI2_COMPRESSION_DELTA, 0, ++ 0); ++ } ++ } ++ /* Unconditionally start this CSI2 channel. */ ++ csi2_start_channel(&cfe->csi2, node->id, fmt->csi_dt, ++ mode, ++ /* Auto arm */ ++ false, ++ /* Pack bytes */ ++ node->id == CSI2_CH1_EMBEDDED ? true : false, ++ width, height); ++ } ++ ++ v4l2_subdev_unlock_state(state); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ if (cfe->job_ready && test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) ++ cfe_prepare_next_job(cfe); ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++} ++ ++static void cfe_stop_channel(struct cfe_node *node, bool fe_stop) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s] fe_stop %u\n", __func__, ++ node_desc[node->id].name, fe_stop); ++ ++ if (fe_stop) { ++ csi2_stop_channel(&cfe->csi2, cfe->fe_csi2_channel); ++ pisp_fe_stop(&cfe->fe); ++ } ++ ++ if (is_csi2_node(node)) ++ csi2_stop_channel(&cfe->csi2, node->id); ++} ++ ++static void cfe_return_buffers(struct cfe_node *node, ++ enum vb2_buffer_state state) ++{ ++ struct cfe_device *cfe = node->cfe; ++ struct cfe_buffer *buf, *tmp; ++ unsigned long flags; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ list_for_each_entry_safe(buf, tmp, &node->dma_queue, list) { ++ list_del(&buf->list); ++ vb2_buffer_done(&buf->vb.vb2_buf, state); ++ } ++ ++ if (node->cur_frm) ++ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, state); ++ if (node->next_frm && node->cur_frm != node->next_frm) ++ vb2_buffer_done(&node->next_frm->vb.vb2_buf, state); ++ ++ node->cur_frm = NULL; ++ node->next_frm = NULL; ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++} ++ ++/* ++ * vb2 ops ++ */ ++ ++static int cfe_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, ++ unsigned int *nplanes, unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vq); ++ struct cfe_device *cfe = node->cfe; ++ unsigned int size = is_image_output_node(node) ? ++ node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (vq->num_buffers + *nbuffers < 3) ++ *nbuffers = 3 - vq->num_buffers; ++ ++ if (*nplanes) { ++ if (sizes[0] < size) { ++ cfe_err("sizes[0] %i < size %u\n", sizes[0], size); ++ return -EINVAL; ++ } ++ size = sizes[0]; ++ } ++ ++ *nplanes = 1; ++ sizes[0] = size; ++ ++ return 0; ++} ++ ++static int cfe_buffer_prepare(struct vb2_buffer *vb) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue); ++ struct cfe_device *cfe = node->cfe; ++ struct cfe_buffer *buf = to_cfe_buffer(vb); ++ unsigned long size; ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, ++ vb); ++ ++ size = is_image_output_node(node) ? node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; ++ if (vb2_plane_size(vb, 0) < size) { ++ cfe_err("data will not fit into plane (%lu < %lu)\n", ++ vb2_plane_size(vb, 0), size); ++ return -EINVAL; ++ } ++ ++ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); ++ ++ if (node->id == FE_CONFIG) { ++ struct cfe_config_buffer *b = to_cfe_config_buffer(buf); ++ void *addr = vb2_plane_vaddr(vb, 0); ++ ++ memcpy(&b->config, addr, sizeof(struct pisp_fe_config)); ++ return pisp_fe_validate_config(&cfe->fe, &b->config, ++ &cfe->node[FE_OUT0].fmt, ++ &cfe->node[FE_OUT1].fmt); ++ } ++ ++ return 0; ++} ++ ++static void cfe_buffer_queue(struct vb2_buffer *vb) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue); ++ struct cfe_device *cfe = node->cfe; ++ struct cfe_buffer *buf = to_cfe_buffer(vb); ++ unsigned long flags; ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, ++ vb); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ ++ list_add_tail(&buf->list, &node->dma_queue); ++ ++ if (!cfe->job_ready) ++ cfe->job_ready = cfe_check_job_ready(cfe); ++ ++ if (!cfe->job_queued && cfe->job_ready && ++ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { ++ cfe_dbg("Preparing job immediately for channel %u\n", ++ node->id); ++ cfe_prepare_next_job(cfe); ++ } ++ ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++} ++ ++static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count) ++{ ++ struct v4l2_mbus_config mbus_config = { 0 }; ++ struct cfe_node *node = vb2_get_drv_priv(vq); ++ struct cfe_device *cfe = node->cfe; ++ int ret; ++ ++ cfe_dbg("%s: [%s] begin.\n", __func__, node_desc[node->id].name); ++ ++ if (!check_state(cfe, NODE_ENABLED, node->id)) { ++ cfe_err("%s node link is not enabled.\n", ++ node_desc[node->id].name); ++ return -EINVAL; ++ } ++ ++ ret = pm_runtime_resume_and_get(&cfe->pdev->dev); ++ if (ret < 0) { ++ cfe_err("pm_runtime_resume_and_get failed\n"); ++ goto err_streaming; ++ } ++ ++ ret = media_pipeline_start(&node->pad, &cfe->pipe); ++ if (ret < 0) { ++ cfe_err("Failed to start media pipeline: %d\n", ret); ++ goto err_pm_put; ++ } ++ ++ clear_state(cfe, FS_INT | FE_INT, node->id); ++ set_state(cfe, NODE_STREAMING, node->id); ++ cfe_start_channel(node); ++ ++ if (!test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { ++ cfe_dbg("Not all nodes are set to streaming yet!\n"); ++ return 0; ++ } ++ ++ cfg_reg_write(cfe, MIPICFG_CFG, MIPICFG_CFG_SEL_CSI); ++ cfg_reg_write(cfe, MIPICFG_INTE, MIPICFG_INT_CSI_DMA | MIPICFG_INT_PISP_FE); ++ ++ cfe->csi2.active_data_lanes = cfe->csi2.dphy.num_lanes; ++ cfe_dbg("Running with %u data lanes\n", cfe->csi2.active_data_lanes); ++ ++ ret = v4l2_subdev_call(cfe->sensor, pad, get_mbus_config, 0, ++ &mbus_config); ++ if (ret < 0 && ret != -ENOIOCTLCMD) { ++ cfe_err("g_mbus_config failed\n"); ++ goto err_pm_put; ++ } ++ ++ cfe->csi2.active_data_lanes = mbus_config.bus.mipi_csi2.num_data_lanes; ++ if (!cfe->csi2.active_data_lanes) ++ cfe->csi2.active_data_lanes = cfe->csi2.dphy.num_lanes; ++ if (cfe->csi2.active_data_lanes > cfe->csi2.dphy.num_lanes) { ++ cfe_err("Device has requested %u data lanes, which is >%u configured in DT\n", ++ cfe->csi2.active_data_lanes, cfe->csi2.dphy.num_lanes); ++ ret = -EINVAL; ++ goto err_disable_cfe; ++ } ++ ++ cfe_dbg("Starting sensor streaming\n"); ++ ++ csi2_open_rx(&cfe->csi2); ++ ++ cfe->sequence = 0; ++ ret = v4l2_subdev_call(cfe->sensor, video, s_stream, 1); ++ if (ret < 0) { ++ cfe_err("stream on failed in subdev\n"); ++ goto err_disable_cfe; ++ } ++ ++ cfe_dbg("%s: [%s] end.\n", __func__, node_desc[node->id].name); ++ ++ return 0; ++ ++err_disable_cfe: ++ csi2_close_rx(&cfe->csi2); ++ cfe_stop_channel(node, true); ++ media_pipeline_stop(&node->pad); ++err_pm_put: ++ pm_runtime_put(&cfe->pdev->dev); ++err_streaming: ++ cfe_return_buffers(node, VB2_BUF_STATE_QUEUED); ++ clear_state(cfe, NODE_STREAMING, node->id); ++ ++ return ret; ++} ++ ++static void cfe_stop_streaming(struct vb2_queue *vq) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vq); ++ struct cfe_device *cfe = node->cfe; ++ unsigned long flags; ++ bool fe_stop; ++ ++ cfe_dbg("%s: [%s] begin.\n", __func__, node_desc[node->id].name); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ fe_stop = is_fe_enabled(cfe) && ++ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); ++ ++ cfe->job_ready = false; ++ clear_state(cfe, NODE_STREAMING, node->id); ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++ ++ cfe_stop_channel(node, fe_stop); ++ ++ if (!test_any_node(cfe, NODE_STREAMING)) { ++ /* Stop streaming the sensor and disable the peripheral. */ ++ if (v4l2_subdev_call(cfe->sensor, video, s_stream, 0) < 0) ++ cfe_err("stream off failed in subdev\n"); ++ ++ csi2_close_rx(&cfe->csi2); ++ ++ cfg_reg_write(cfe, MIPICFG_INTE, 0); ++ } ++ ++ media_pipeline_stop(&node->pad); ++ ++ /* Clear all queued buffers for the node */ ++ cfe_return_buffers(node, VB2_BUF_STATE_ERROR); ++ ++ pm_runtime_put(&cfe->pdev->dev); ++ ++ cfe_dbg("%s: [%s] end.\n", __func__, node_desc[node->id].name); ++} ++ ++static const struct vb2_ops cfe_video_qops = { ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++ .queue_setup = cfe_queue_setup, ++ .buf_prepare = cfe_buffer_prepare, ++ .buf_queue = cfe_buffer_queue, ++ .start_streaming = cfe_start_streaming, ++ .stop_streaming = cfe_stop_streaming, ++}; ++ ++/* ++ * v4l2 ioctl ops ++ */ ++ ++static int cfe_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ strscpy(cap->driver, CFE_MODULE_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, CFE_MODULE_NAME, sizeof(cap->card)); ++ ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", ++ dev_name(&cfe->pdev->dev)); ++ ++ cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE | ++ V4L2_CAP_META_OUTPUT; ++ ++ return 0; ++} ++ ++static int cfe_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ unsigned int i, j; ++ ++ if (!is_image_output_node(node)) ++ return -EINVAL; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) { ++ if (f->mbus_code && formats[i].code != f->mbus_code) ++ continue; ++ ++ if (formats[i].flags & CFE_FORMAT_FLAG_META_OUT || ++ formats[i].flags & CFE_FORMAT_FLAG_META_CAP) ++ continue; ++ ++ if (is_fe_node(node) && ++ !(formats[i].flags & CFE_FORMAT_FLAG_FE_OUT)) ++ continue; ++ ++ if (j == f->index) { ++ f->pixelformat = formats[i].fourcc; ++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ return 0; ++ } ++ j++; ++ } ++ ++ return -EINVAL; ++} ++ ++static int cfe_g_fmt(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (f->type != node->buffer_queue.type) ++ return -EINVAL; ++ ++ *f = node->fmt; ++ ++ return 0; ++} ++ ++static int try_fmt_vid_cap(struct cfe_node *node, struct v4l2_format *f) ++{ ++ struct cfe_device *cfe = node->cfe; ++ const struct cfe_fmt *fmt; ++ ++ cfe_dbg("%s: [%s] %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", ++ __func__, node_desc[node->id].name, ++ f->fmt.pix.width, f->fmt.pix.height, ++ V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat)); ++ ++ if (!is_image_output_node(node)) ++ return -EINVAL; ++ ++ /* ++ * Default to a format that works for both CSI2 and FE. ++ */ ++ fmt = find_format_by_pix(f->fmt.pix.pixelformat); ++ if (!fmt) ++ fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ ++ f->fmt.pix.pixelformat = fmt->fourcc; ++ ++ if (is_fe_node(node) && fmt->remap[CFE_REMAP_16BIT]) { ++ f->fmt.pix.pixelformat = fmt->remap[CFE_REMAP_16BIT]; ++ fmt = find_format_by_pix(f->fmt.pix.pixelformat); ++ } ++ ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ ++ cfe_calc_format_size_bpl(cfe, fmt, f); ++ ++ return 0; ++} ++ ++static int cfe_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ struct vb2_queue *q = &node->buffer_queue; ++ int ret; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (vb2_is_busy(q)) ++ return -EBUSY; ++ ++ ret = try_fmt_vid_cap(node, f); ++ if (ret) ++ return ret; ++ ++ node->fmt = *f; ++ ++ cfe_dbg("%s: Set %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", __func__, ++ node->fmt.fmt.pix.width, node->fmt.fmt.pix.height, ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat)); ++ ++ return 0; ++} ++ ++static int cfe_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ return try_fmt_vid_cap(node, f); ++} ++ ++static int cfe_enum_fmt_meta(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (!is_meta_node(node) || f->index != 0) ++ return -EINVAL; ++ ++ switch (node->id) { ++ case CSI2_CH1_EMBEDDED: ++ f->pixelformat = V4L2_META_FMT_SENSOR_DATA; ++ return 0; ++ case FE_STATS: ++ f->pixelformat = V4L2_META_FMT_RPI_FE_STATS; ++ return 0; ++ case FE_CONFIG: ++ f->pixelformat = V4L2_META_FMT_RPI_FE_CFG; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int try_fmt_meta(struct cfe_node *node, struct v4l2_format *f) ++{ ++ switch (node->id) { ++ case CSI2_CH1_EMBEDDED: ++ f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA; ++ if (!f->fmt.meta.buffersize) ++ f->fmt.meta.buffersize = DEFAULT_EMBEDDED_SIZE; ++ f->fmt.meta.buffersize = ++ min_t(u32, f->fmt.meta.buffersize, MAX_BUFFER_SIZE); ++ f->fmt.meta.buffersize = ++ ALIGN(f->fmt.meta.buffersize, BPL_ALIGNMENT); ++ return 0; ++ case FE_STATS: ++ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_STATS; ++ f->fmt.meta.buffersize = sizeof(struct pisp_statistics); ++ return 0; ++ case FE_CONFIG: ++ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_CFG; ++ f->fmt.meta.buffersize = sizeof(struct pisp_fe_config); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int cfe_s_fmt_meta(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ struct vb2_queue *q = &node->buffer_queue; ++ int ret; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (vb2_is_busy(q)) ++ return -EBUSY; ++ ++ if (f->type != node->buffer_queue.type) ++ return -EINVAL; ++ ++ ret = try_fmt_meta(node, f); ++ if (ret) ++ return ret; ++ ++ node->fmt = *f; ++ ++ cfe_dbg("%s: Set " V4L2_FOURCC_CONV "\n", __func__, ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat)); ++ ++ return 0; ++} ++ ++static int cfe_try_fmt_meta(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ return try_fmt_meta(node, f); ++} ++ ++static int cfe_enum_framesizes(struct file *file, void *priv, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ const struct cfe_fmt *fmt; ++ ++ cfe_dbg("%s [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (fsize->index > 0) ++ return -EINVAL; ++ ++ /* check for valid format */ ++ fmt = find_format_by_pix(fsize->pixel_format); ++ if (!fmt) { ++ cfe_dbg("Invalid pixel code: %x\n", fsize->pixel_format); ++ return -EINVAL; ++ } ++ ++ /* TODO: Do we have limits on the step_width? */ ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise.min_width = MIN_WIDTH; ++ fsize->stepwise.max_width = MAX_WIDTH; ++ fsize->stepwise.step_width = 2; ++ fsize->stepwise.min_height = MIN_HEIGHT; ++ fsize->stepwise.max_height = MAX_HEIGHT; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static int cfe_subscribe_event(struct v4l2_fh *fh, ++ const struct v4l2_event_subscription *sub) ++{ ++ struct cfe_node *node = video_get_drvdata(fh->vdev); ++ ++ switch (sub->type) { ++ case V4L2_EVENT_FRAME_SYNC: ++ if (!is_image_output_node(node)) ++ break; ++ ++ return v4l2_event_subscribe(fh, sub, 2, NULL); ++ case V4L2_EVENT_SOURCE_CHANGE: ++ if (is_meta_input_node(node)) ++ break; ++ ++ return v4l2_event_subscribe(fh, sub, 4, NULL); ++ } ++ ++ return v4l2_ctrl_subscribe_event(fh, sub); ++} ++ ++static const struct v4l2_ioctl_ops cfe_ioctl_ops = { ++ .vidioc_querycap = cfe_querycap, ++ .vidioc_enum_fmt_vid_cap = cfe_enum_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap = cfe_g_fmt, ++ .vidioc_s_fmt_vid_cap = cfe_s_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = cfe_try_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_meta_cap = cfe_enum_fmt_meta, ++ .vidioc_g_fmt_meta_cap = cfe_g_fmt, ++ .vidioc_s_fmt_meta_cap = cfe_s_fmt_meta, ++ .vidioc_try_fmt_meta_cap = cfe_try_fmt_meta, ++ ++ .vidioc_enum_fmt_meta_out = cfe_enum_fmt_meta, ++ .vidioc_g_fmt_meta_out = cfe_g_fmt, ++ .vidioc_s_fmt_meta_out = cfe_s_fmt_meta, ++ .vidioc_try_fmt_meta_out = cfe_try_fmt_meta, ++ ++ .vidioc_enum_framesizes = cfe_enum_framesizes, ++ ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, ++ ++ .vidioc_subscribe_event = cfe_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++static void cfe_notify(struct v4l2_subdev *sd, unsigned int notification, ++ void *arg) ++{ ++ struct cfe_device *cfe = to_cfe_device(sd->v4l2_dev); ++ unsigned int i; ++ ++ switch (notification) { ++ case V4L2_DEVICE_NOTIFY_EVENT: ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (check_state(cfe, NODE_REGISTERED, i)) ++ continue; ++ ++ v4l2_event_queue(&node->video_dev, arg); ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++/* cfe capture driver file operations */ ++static const struct v4l2_file_operations cfe_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = vb2_fop_release, ++ .poll = vb2_fop_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = vb2_fop_mmap, ++}; ++ ++static int cfe_video_link_validate(struct media_link *link) ++{ ++ struct video_device *vd = container_of(link->sink->entity, ++ struct video_device, entity); ++ struct cfe_node *node = container_of(vd, struct cfe_node, video_dev); ++ struct cfe_device *cfe = node->cfe; ++ struct v4l2_mbus_framefmt *source_fmt; ++ struct v4l2_subdev_state *state; ++ struct v4l2_subdev *source_sd; ++ int ret = 0; ++ ++ cfe_dbg("%s: [%s] link \"%s\":%u -> \"%s\":%u\n", __func__, ++ node_desc[node->id].name, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index); ++ ++ if (!media_entity_remote_source_pad_unique(link->sink->entity)) { ++ cfe_err("video node %s pad not connected\n", vd->name); ++ return -ENOTCONN; ++ } ++ ++ source_sd = media_entity_to_v4l2_subdev(link->source->entity); ++ ++ state = v4l2_subdev_lock_and_get_active_state(source_sd); ++ ++ source_fmt = v4l2_subdev_get_pad_format(source_sd, state, ++ link->source->index); ++ if (!source_fmt) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (is_image_output_node(node)) { ++ struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix; ++ const struct cfe_fmt *fmt; ++ ++ if (source_fmt->width != pix_fmt->width || ++ source_fmt->height != pix_fmt->height) { ++ cfe_err("Wrong width or height %ux%u (remote pad set to %ux%u)\n", ++ pix_fmt->width, pix_fmt->height, ++ source_fmt->width, ++ source_fmt->height); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ fmt = find_format_by_code(source_fmt->code); ++ if (!fmt || fmt->fourcc != pix_fmt->pixelformat) { ++ cfe_err("Format mismatch!\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ } else if (node->id == CSI2_CH1_EMBEDDED) { ++ struct v4l2_meta_format *meta_fmt = &node->fmt.fmt.meta; ++ ++ if (source_fmt->width * source_fmt->height != ++ meta_fmt->buffersize || ++ source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) { ++ cfe_err("WARNING: Wrong metadata width/height/code %ux%u %08x (remote pad set to %ux%u %08x)\n", ++ meta_fmt->buffersize, 1, ++ MEDIA_BUS_FMT_SENSOR_DATA, ++ source_fmt->width, ++ source_fmt->height, ++ source_fmt->code); ++ /* TODO: this should throw an error eventually */ ++ } ++ } ++ ++out: ++ v4l2_subdev_unlock_state(state); ++ ++ return ret; ++} ++ ++static const struct media_entity_operations cfe_media_entity_ops = { ++ .link_validate = cfe_video_link_validate, ++}; ++ ++static int cfe_video_link_notify(struct media_link *link, u32 flags, ++ unsigned int notification) ++{ ++ struct media_device *mdev = link->graph_obj.mdev; ++ struct cfe_device *cfe = container_of(mdev, struct cfe_device, mdev); ++ struct media_entity *fe = &cfe->fe.sd.entity; ++ struct media_entity *csi2 = &cfe->csi2.sd.entity; ++ unsigned long lock_flags; ++ unsigned int i; ++ ++ if (notification != MEDIA_DEV_NOTIFY_POST_LINK_CH) ++ return 0; ++ ++ cfe_dbg("%s: %s[%u] -> %s[%u] 0x%x", __func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index, flags); ++ ++ spin_lock_irqsave(&cfe->state_lock, lock_flags); ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (link->sink->entity != &cfe->node[i].video_dev.entity && ++ link->source->entity != &cfe->node[i].video_dev.entity) ++ continue; ++ ++ if (link->flags & MEDIA_LNK_FL_ENABLED) ++ set_state(cfe, NODE_ENABLED, i); ++ else ++ clear_state(cfe, NODE_ENABLED, i); ++ ++ break; ++ } ++ ++ spin_unlock_irqrestore(&cfe->state_lock, lock_flags); ++ ++ if (link->source->entity != csi2) ++ return 0; ++ if (link->sink->index != 0) ++ return 0; ++ if (link->source->index == node_desc[CSI2_CH1_EMBEDDED].link_pad) ++ return 0; ++ ++ cfe->fe_csi2_channel = -1; ++ if (link->sink->entity == fe && (link->flags & MEDIA_LNK_FL_ENABLED)) { ++ if (link->source->index == node_desc[CSI2_CH0].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH0; ++ else if (link->source->index == node_desc[CSI2_CH2].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH2; ++ else if (link->source->index == node_desc[CSI2_CH3].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH3; ++ } ++ ++ if (is_fe_enabled(cfe)) ++ cfe_dbg("%s: Found CSI2:%d -> FE:0 link\n", __func__, ++ cfe->fe_csi2_channel); ++ else ++ cfe_dbg("%s: Unable to find CSI2:x -> FE:0 link\n", __func__); ++ ++ return 0; ++} ++ ++static const struct media_device_ops cfe_media_device_ops = { ++ .link_notify = cfe_video_link_notify, ++}; ++ ++static void cfe_release(struct kref *kref) ++{ ++ struct cfe_device *cfe = container_of(kref, struct cfe_device, kref); ++ ++ media_device_cleanup(&cfe->mdev); ++ ++ kfree(cfe); ++} ++ ++static void cfe_put(struct cfe_device *cfe) ++{ ++ kref_put(&cfe->kref, cfe_release); ++} ++ ++static void cfe_get(struct cfe_device *cfe) ++{ ++ kref_get(&cfe->kref); ++} ++ ++static void cfe_node_release(struct video_device *vdev) ++{ ++ struct cfe_node *node = video_get_drvdata(vdev); ++ ++ cfe_put(node->cfe); ++} ++ ++static int cfe_register_node(struct cfe_device *cfe, int id) ++{ ++ struct video_device *vdev; ++ const struct cfe_fmt *fmt; ++ struct vb2_queue *q; ++ struct cfe_node *node = &cfe->node[id]; ++ int ret; ++ ++ node->cfe = cfe; ++ node->id = id; ++ ++ if (is_image_output_node(node)) { ++ fmt = find_format_by_code(cfe_default_format.code); ++ if (!fmt) { ++ cfe_err("Failed to find format code\n"); ++ return -EINVAL; ++ } ++ ++ node->fmt.fmt.pix.pixelformat = fmt->fourcc; ++ v4l2_fill_pix_format(&node->fmt.fmt.pix, &cfe_default_format); ++ ++ ret = try_fmt_vid_cap(node, &node->fmt); ++ if (ret) ++ return ret; ++ } else { ++ ret = try_fmt_meta(node, &node->fmt); ++ if (ret) ++ return ret; ++ } ++ node->fmt.type = node_desc[id].buf_type; ++ ++ mutex_init(&node->lock); ++ ++ q = &node->buffer_queue; ++ q->type = node_desc[id].buf_type; ++ q->io_modes = VB2_MMAP | VB2_DMABUF; ++ q->drv_priv = node; ++ q->ops = &cfe_video_qops; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->buf_struct_size = id == FE_CONFIG ? sizeof(struct cfe_config_buffer) ++ : sizeof(struct cfe_buffer); ++ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ q->lock = &node->lock; ++ q->min_buffers_needed = 1; ++ q->dev = &cfe->pdev->dev; ++ ++ ret = vb2_queue_init(q); ++ if (ret) { ++ cfe_err("vb2_queue_init() failed\n"); ++ return ret; ++ } ++ ++ INIT_LIST_HEAD(&node->dma_queue); ++ ++ vdev = &node->video_dev; ++ vdev->release = cfe_node_release; ++ vdev->fops = &cfe_fops; ++ vdev->ioctl_ops = &cfe_ioctl_ops; ++ vdev->entity.ops = &cfe_media_entity_ops; ++ vdev->v4l2_dev = &cfe->v4l2_dev; ++ vdev->vfl_dir = (is_image_output_node(node) || is_meta_output_node(node)) ++ ? VFL_DIR_RX : VFL_DIR_TX; ++ vdev->queue = q; ++ vdev->lock = &node->lock; ++ vdev->device_caps = node_desc[id].cap; ++ vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; ++ ++ /* Define the device names */ ++ snprintf(vdev->name, sizeof(vdev->name), "%s-%s", CFE_MODULE_NAME, ++ node_desc[id].name); ++ ++ video_set_drvdata(vdev, node); ++ if (node->id == FE_OUT0) ++ vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT; ++ node->pad.flags = node_desc[id].pad_flags; ++ media_entity_pads_init(&vdev->entity, 1, &node->pad); ++ ++ if (is_meta_node(node)) { ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_ENUM_FRAMEINTERVALS); ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_ENUM_FRAMESIZES); ++ } ++ ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); ++ if (ret) { ++ cfe_err("Unable to register video device %s\n", vdev->name); ++ return ret; ++ } ++ ++ cfe_info("Registered [%s] node id %d successfully as /dev/video%u\n", ++ vdev->name, id, vdev->num); ++ ++ /* ++ * Acquire a reference to cfe, which will be released when the video ++ * device will be unregistered and userspace will have closed all open ++ * file handles. ++ */ ++ cfe_get(cfe); ++ set_state(cfe, NODE_REGISTERED, id); ++ ++ return 0; ++} ++ ++static void cfe_unregister_nodes(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (check_state(cfe, NODE_REGISTERED, i)) { ++ clear_state(cfe, NODE_REGISTERED, i); ++ video_unregister_device(&node->video_dev); ++ } ++ } ++} ++ ++static int cfe_link_node_pads(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ int ret; ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (!check_state(cfe, NODE_REGISTERED, i)) ++ continue; ++ ++ if (i < cfe->sensor->entity.num_pads) { ++ /* Sensor -> CSI2 */ ++ ret = media_create_pad_link(&cfe->sensor->entity, i, ++ &cfe->csi2.sd.entity, i, ++ MEDIA_LNK_FL_IMMUTABLE | ++ MEDIA_LNK_FL_ENABLED); ++ if (ret) ++ return ret; ++ } ++ ++ /* CSI2 channel # -> /dev/video# */ ++ ret = media_create_pad_link(&cfe->csi2.sd.entity, ++ node_desc[i].link_pad, ++ &node->video_dev.entity, 0, 0); ++ if (ret) ++ return ret; ++ ++ if (node->id != CSI2_CH1_EMBEDDED) { ++ /* CSI2 channel # -> FE Input */ ++ ret = media_create_pad_link(&cfe->csi2.sd.entity, ++ node_desc[i].link_pad, ++ &cfe->fe.sd.entity, ++ FE_STREAM_PAD, 0); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ for (; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ struct media_entity *src, *dst; ++ unsigned int src_pad, dst_pad; ++ ++ if (node_desc[i].pad_flags & MEDIA_PAD_FL_SINK) { ++ /* FE -> /dev/video# */ ++ src = &cfe->fe.sd.entity; ++ src_pad = node_desc[i].link_pad; ++ dst = &node->video_dev.entity; ++ dst_pad = 0; ++ } else { ++ /* /dev/video# -> FE */ ++ dst = &cfe->fe.sd.entity; ++ dst_pad = node_desc[i].link_pad; ++ src = &node->video_dev.entity; ++ src_pad = 0; ++ } ++ ++ ret = media_create_pad_link(src, src_pad, dst, dst_pad, 0); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int cfe_probe_complete(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ int ret; ++ ++ cfe->v4l2_dev.notify = cfe_notify; ++ ++ cfe->sensor_embedded_data = (cfe->sensor->entity.num_pads >= 2); ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ ret = cfe_register_node(cfe, i); ++ if (ret) { ++ cfe_err("Unable to register video node %u.\n", i); ++ goto unregister; ++ } ++ } ++ ++ ret = cfe_link_node_pads(cfe); ++ if (ret) { ++ cfe_err("Unable to link node pads.\n"); ++ goto unregister; ++ } ++ ++ ret = v4l2_device_register_subdev_nodes(&cfe->v4l2_dev); ++ if (ret) { ++ cfe_err("Unable to register subdev nodes.\n"); ++ goto unregister; ++ } ++ ++ /* ++ * Release the initial reference, all references are now owned by the ++ * video devices. ++ */ ++ cfe_put(cfe); ++ return 0; ++ ++unregister: ++ cfe_unregister_nodes(cfe); ++ cfe_put(cfe); ++ ++ return ret; ++} ++ ++static int cfe_async_bound(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *subdev, ++ struct v4l2_async_subdev *asd) ++{ ++ struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev); ++ ++ if (cfe->sensor) { ++ cfe_info("Rejecting subdev %s (Already set!!)", subdev->name); ++ return 0; ++ } ++ ++ cfe->sensor = subdev; ++ cfe_info("Using sensor %s for capture\n", subdev->name); ++ ++ return 0; ++} ++ ++static int cfe_async_complete(struct v4l2_async_notifier *notifier) ++{ ++ struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev); ++ ++ return cfe_probe_complete(cfe); ++} ++ ++static const struct v4l2_async_notifier_operations cfe_async_ops = { ++ .bound = cfe_async_bound, ++ .complete = cfe_async_complete, ++}; ++ ++static int of_cfe_connect_subdevs(struct cfe_device *cfe) ++{ ++ struct platform_device *pdev = cfe->pdev; ++ struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; ++ struct device_node *node = pdev->dev.of_node; ++ struct device_node *ep_node; ++ struct device_node *sensor_node; ++ unsigned int lane; ++ int ret = -EINVAL; ++ ++ /* Get the local endpoint and remote device. */ ++ ep_node = of_graph_get_next_endpoint(node, NULL); ++ if (!ep_node) { ++ cfe_err("can't get next endpoint\n"); ++ return -EINVAL; ++ } ++ ++ cfe_dbg("ep_node is %pOF\n", ep_node); ++ ++ sensor_node = of_graph_get_remote_port_parent(ep_node); ++ if (!sensor_node) { ++ cfe_err("can't get remote parent\n"); ++ goto cleanup_exit; ++ } ++ ++ cfe_info("found subdevice %pOF\n", sensor_node); ++ ++ /* Parse the local endpoint and validate its configuration. */ ++ v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), &ep); ++ ++ cfe->csi2.multipacket_line = ++ fwnode_property_present(of_fwnode_handle(ep_node), ++ "multipacket-line"); ++ ++ if (ep.bus_type != V4L2_MBUS_CSI2_DPHY) { ++ cfe_err("endpoint node type != CSI2\n"); ++ return -EINVAL; ++ } ++ ++ for (lane = 0; lane < ep.bus.mipi_csi2.num_data_lanes; lane++) { ++ if (ep.bus.mipi_csi2.data_lanes[lane] != lane + 1) { ++ cfe_err("subdevice %pOF: data lanes reordering not supported\n", ++ sensor_node); ++ goto cleanup_exit; ++ } ++ } ++ ++ /* TODO: Get the frequency from devicetree */ ++ cfe->csi2.dphy.dphy_freq = 999; ++ cfe->csi2.dphy.num_lanes = ep.bus.mipi_csi2.num_data_lanes; ++ cfe->csi2.bus_flags = ep.bus.mipi_csi2.flags; ++ ++ cfe_dbg("subdevice %pOF: %u data lanes, flags=0x%08x, multipacket_line=%u\n", ++ sensor_node, cfe->csi2.dphy.num_lanes, cfe->csi2.bus_flags, ++ cfe->csi2.multipacket_line); ++ ++ /* Initialize and register the async notifier. */ ++ v4l2_async_nf_init(&cfe->notifier); ++ cfe->notifier.ops = &cfe_async_ops; ++ ++ cfe->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; ++ cfe->asd.match.fwnode = of_fwnode_handle(sensor_node); ++ ret = __v4l2_async_nf_add_subdev(&cfe->notifier, &cfe->asd); ++ if (ret) { ++ cfe_err("Error adding subdevice: %d\n", ret); ++ goto cleanup_exit; ++ } ++ ++ ret = v4l2_async_nf_register(&cfe->v4l2_dev, &cfe->notifier); ++ if (ret) { ++ cfe_err("Error registering async notifier: %d\n", ret); ++ ret = -EINVAL; ++ } ++ ++cleanup_exit: ++ of_node_put(sensor_node); ++ of_node_put(ep_node); ++ ++ return ret; ++} ++ ++static int cfe_probe(struct platform_device *pdev) ++{ ++ struct cfe_device *cfe; ++ char debugfs_name[32]; ++ int ret; ++ ++ cfe = kzalloc(sizeof(*cfe), GFP_KERNEL); ++ if (!cfe) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, cfe); ++ ++ kref_init(&cfe->kref); ++ cfe->pdev = pdev; ++ cfe->fe_csi2_channel = -1; ++ spin_lock_init(&cfe->state_lock); ++ ++ cfe->csi2.base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(cfe->csi2.base)) { ++ dev_err(&pdev->dev, "Failed to get dma io block\n"); ++ ret = PTR_ERR(cfe->csi2.base); ++ goto err_cfe_put; ++ } ++ ++ cfe->csi2.dphy.base = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(cfe->csi2.dphy.base)) { ++ dev_err(&pdev->dev, "Failed to get host io block\n"); ++ ret = PTR_ERR(cfe->csi2.dphy.base); ++ goto err_cfe_put; ++ } ++ ++ cfe->mipi_cfg_base = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(cfe->mipi_cfg_base)) { ++ dev_err(&pdev->dev, "Failed to get mipi cfg io block\n"); ++ ret = PTR_ERR(cfe->mipi_cfg_base); ++ goto err_cfe_put; ++ } ++ ++ cfe->fe.base = devm_platform_ioremap_resource(pdev, 3); ++ if (IS_ERR(cfe->fe.base)) { ++ dev_err(&pdev->dev, "Failed to get pisp fe io block\n"); ++ ret = PTR_ERR(cfe->fe.base); ++ goto err_cfe_put; ++ } ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret <= 0) { ++ dev_err(&pdev->dev, "No IRQ resource\n"); ++ ret = -EINVAL; ++ goto err_cfe_put; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, ret, cfe_isr, 0, "rp1-cfe", cfe); ++ if (ret) { ++ dev_err(&pdev->dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_cfe_put; ++ } ++ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); ++ if (ret) { ++ dev_err(&pdev->dev, "DMA enable failed\n"); ++ goto err_cfe_put; ++ } ++ ++ /* TODO: Enable clock only when running. */ ++ cfe->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(cfe->clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(cfe->clk), ++ "clock not found\n"); ++ ++ cfe->mdev.dev = &pdev->dev; ++ cfe->mdev.ops = &cfe_media_device_ops; ++ strscpy(cfe->mdev.model, CFE_MODULE_NAME, sizeof(cfe->mdev.model)); ++ strscpy(cfe->mdev.serial, "", sizeof(cfe->mdev.serial)); ++ snprintf(cfe->mdev.bus_info, sizeof(cfe->mdev.bus_info), "platform:%s", ++ dev_name(&pdev->dev)); ++ ++ media_device_init(&cfe->mdev); ++ ++ cfe->v4l2_dev.mdev = &cfe->mdev; ++ ++ ret = v4l2_device_register(&pdev->dev, &cfe->v4l2_dev); ++ if (ret) { ++ cfe_err("Unable to register v4l2 device.\n"); ++ goto err_cfe_put; ++ } ++ ++ snprintf(debugfs_name, sizeof(debugfs_name), "rp1-cfe:%s", ++ dev_name(&pdev->dev)); ++ cfe->debugfs = debugfs_create_dir(debugfs_name, NULL); ++ debugfs_create_file("format", 0444, cfe->debugfs, cfe, &format_fops); ++ debugfs_create_file("regs", 0444, cfe->debugfs, cfe, ++ &mipi_cfg_regs_fops); ++ ++ /* Enable the block power domain */ ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = pm_runtime_resume_and_get(&cfe->pdev->dev); ++ if (ret) ++ goto err_runtime_disable; ++ ++ cfe->csi2.v4l2_dev = &cfe->v4l2_dev; ++ ret = csi2_init(&cfe->csi2, cfe->debugfs); ++ if (ret) { ++ cfe_err("Failed to init csi2 (%d)\n", ret); ++ goto err_runtime_put; ++ } ++ ++ cfe->fe.v4l2_dev = &cfe->v4l2_dev; ++ ret = pisp_fe_init(&cfe->fe, cfe->debugfs); ++ if (ret) { ++ cfe_err("Failed to init pisp fe (%d)\n", ret); ++ goto err_csi2_uninit; ++ } ++ ++ cfe->mdev.hw_revision = cfe->fe.hw_revision; ++ ret = media_device_register(&cfe->mdev); ++ if (ret < 0) { ++ cfe_err("Unable to register media-controller device.\n"); ++ goto err_pisp_fe_uninit; ++ } ++ ++ ret = of_cfe_connect_subdevs(cfe); ++ if (ret) { ++ cfe_err("Failed to connect subdevs\n"); ++ goto err_media_unregister; ++ } ++ ++ pm_runtime_put(&cfe->pdev->dev); ++ ++ return 0; ++ ++err_media_unregister: ++ media_device_unregister(&cfe->mdev); ++err_pisp_fe_uninit: ++ pisp_fe_uninit(&cfe->fe); ++err_csi2_uninit: ++ csi2_uninit(&cfe->csi2); ++err_runtime_put: ++ pm_runtime_put(&cfe->pdev->dev); ++err_runtime_disable: ++ pm_runtime_disable(&pdev->dev); ++ debugfs_remove(cfe->debugfs); ++ v4l2_device_unregister(&cfe->v4l2_dev); ++err_cfe_put: ++ cfe_put(cfe); ++ ++ return ret; ++} ++ ++static int cfe_remove(struct platform_device *pdev) ++{ ++ struct cfe_device *cfe = platform_get_drvdata(pdev); ++ ++ debugfs_remove(cfe->debugfs); ++ ++ v4l2_async_nf_unregister(&cfe->notifier); ++ media_device_unregister(&cfe->mdev); ++ cfe_unregister_nodes(cfe); ++ ++ pisp_fe_uninit(&cfe->fe); ++ csi2_uninit(&cfe->csi2); ++ ++ pm_runtime_disable(&pdev->dev); ++ ++ v4l2_device_unregister(&cfe->v4l2_dev); ++ ++ return 0; ++} ++ ++static int cfe_runtime_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct cfe_device *cfe = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(cfe->clk); ++ ++ return 0; ++} ++ ++static int cfe_runtime_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct cfe_device *cfe = platform_get_drvdata(pdev); ++ int ret; ++ ++ ret = clk_prepare_enable(cfe->clk); ++ if (ret) { ++ dev_err(dev, "Unable to enable clock\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops cfe_pm_ops = { ++ SET_RUNTIME_PM_OPS(cfe_runtime_suspend, cfe_runtime_resume, NULL) ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) ++}; ++ ++static const struct of_device_id cfe_of_match[] = { ++ { .compatible = "raspberrypi,rp1-cfe" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, cfe_of_match); ++ ++static struct platform_driver cfe_driver = { ++ .probe = cfe_probe, ++ .remove = cfe_remove, ++ .driver = { ++ .name = CFE_MODULE_NAME, ++ .of_match_table = cfe_of_match, ++ .pm = &cfe_pm_ops, ++ }, ++}; ++ ++module_platform_driver(cfe_driver); ++ ++MODULE_AUTHOR("Naushir Patuck "); ++MODULE_DESCRIPTION("RP1 Camera Front End driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(CFE_VERSION); +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -0,0 +1,40 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 CFE driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _RP1_CFE_ ++#define _RP1_CFE_ ++ ++#include ++#include ++#include ++ ++extern bool cfe_debug_irq; ++ ++enum cfe_remap_types { ++ CFE_REMAP_16BIT, ++ CFE_REMAP_COMPRESSED, ++ CFE_NUM_REMAP, ++}; ++ ++#define CFE_FORMAT_FLAG_META_OUT BIT(0) ++#define CFE_FORMAT_FLAG_META_CAP BIT(1) ++#define CFE_FORMAT_FLAG_FE_OUT BIT(2) ++ ++struct cfe_fmt { ++ u32 fourcc; ++ u32 code; ++ u8 depth; ++ u8 csi_dt; ++ u32 remap[CFE_NUM_REMAP]; ++ u32 flags; ++}; ++ ++extern const struct v4l2_mbus_framefmt cfe_default_format; ++extern const struct v4l2_mbus_framefmt cfe_default_meta_format; ++ ++const struct cfe_fmt *find_format_by_code(u32 code); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -0,0 +1,294 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 Camera Front End formats definition ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _CFE_FMTS_H_ ++#define _CFE_FMTS_H_ ++ ++#include "cfe.h" ++ ++static const struct cfe_fmt formats[] = { ++ /* YUV Formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .code = MEDIA_BUS_FMT_YUYV8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .code = MEDIA_BUS_FMT_UYVY8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .code = MEDIA_BUS_FMT_YVYU8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .code = MEDIA_BUS_FMT_VYUY8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ /* RGB Formats */ ++ .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ ++ .code = MEDIA_BUS_FMT_RGB565_2X8_LE, ++ .depth = 16, ++ .csi_dt = 0x22, ++ }, ++ { .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ ++ .code = MEDIA_BUS_FMT_RGB565_2X8_BE, ++ .depth = 16, ++ .csi_dt = 0x22 ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */ ++ .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, ++ .depth = 16, ++ .csi_dt = 0x21, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ ++ .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, ++ .depth = 16, ++ .csi_dt = 0x21, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ ++ .code = MEDIA_BUS_FMT_RGB888_1X24, ++ .depth = 24, ++ .csi_dt = 0x24, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ ++ .code = MEDIA_BUS_FMT_BGR888_1X24, ++ .depth = 24, ++ .csi_dt = 0x24, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ ++ .code = MEDIA_BUS_FMT_ARGB8888_1X32, ++ .depth = 32, ++ .csi_dt = 0x0, ++ }, ++ ++ /* Bayer Formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .code = MEDIA_BUS_FMT_SBGGR8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG8, ++ .code = MEDIA_BUS_FMT_SGBRG8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG8, ++ .code = MEDIA_BUS_FMT_SGRBG8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB8, ++ .code = MEDIA_BUS_FMT_SRGGB8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR10P, ++ .code = MEDIA_BUS_FMT_SBGGR10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG10P, ++ .code = MEDIA_BUS_FMT_SGBRG10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG10P, ++ .code = MEDIA_BUS_FMT_SGRBG10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB10P, ++ .code = MEDIA_BUS_FMT_SRGGB10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR12P, ++ .code = MEDIA_BUS_FMT_SBGGR12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG12P, ++ .code = MEDIA_BUS_FMT_SGBRG12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG12P, ++ .code = MEDIA_BUS_FMT_SGRBG12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB12P, ++ .code = MEDIA_BUS_FMT_SRGGB12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR14P, ++ .code = MEDIA_BUS_FMT_SBGGR14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG14P, ++ .code = MEDIA_BUS_FMT_SGBRG14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG14P, ++ .code = MEDIA_BUS_FMT_SGRBG14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB14P, ++ .code = MEDIA_BUS_FMT_SRGGB14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .code = MEDIA_BUS_FMT_SBGGR16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG16, ++ .code = MEDIA_BUS_FMT_SGBRG16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG16, ++ .code = MEDIA_BUS_FMT_SGRBG16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB16, ++ .code = MEDIA_BUS_FMT_SRGGB16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ /* PiSP Compressed Mode 1 */ ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_RGGB, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_BGGR, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_GBRG, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_GRBG, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ /* Greyscale format */ ++ { ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .code = MEDIA_BUS_FMT_Y8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y10P, ++ .code = MEDIA_BUS_FMT_Y10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_Y16 }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y12P, ++ .code = MEDIA_BUS_FMT_Y12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_Y16 }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y14P, ++ .code = MEDIA_BUS_FMT_Y14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_Y16 }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ ++ /* Embedded data format */ ++ { ++ .fourcc = V4L2_META_FMT_SENSOR_DATA, ++ .code = MEDIA_BUS_FMT_SENSOR_DATA, ++ .depth = 8, ++ .csi_dt = 0x12, ++ .flags = CFE_FORMAT_FLAG_META_CAP, ++ }, ++ ++ /* Frontend formats */ ++ { ++ .fourcc = V4L2_META_FMT_RPI_FE_CFG, ++ .flags = CFE_FORMAT_FLAG_META_OUT, ++ }, ++ { ++ .fourcc = V4L2_META_FMT_RPI_FE_STATS, ++ .flags = CFE_FORMAT_FLAG_META_CAP, ++ }, ++}; ++ ++#endif /* _CFE_FMTS_H_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -0,0 +1,446 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RP1 CSI-2 Driver ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "csi2.h" ++#include "cfe.h" ++ ++#define csi2_dbg_irq(fmt, arg...) \ ++ do { \ ++ if (cfe_debug_irq) \ ++ dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg); \ ++ } while (0) ++#define csi2_dbg(fmt, arg...) dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg) ++#define csi2_info(fmt, arg...) dev_info(csi2->v4l2_dev->dev, fmt, ##arg) ++#define csi2_err(fmt, arg...) dev_err(csi2->v4l2_dev->dev, fmt, ##arg) ++ ++/* CSI2-DMA registers */ ++#define CSI2_STATUS 0x000 ++#define CSI2_QOS 0x004 ++#define CSI2_DISCARDS_OVERFLOW 0x008 ++#define CSI2_DISCARDS_INACTIVE 0x00c ++#define CSI2_DISCARDS_UNMATCHED 0x010 ++#define CSI2_DISCARDS_LEN_LIMIT 0x014 ++#define CSI2_LLEV_PANICS 0x018 ++#define CSI2_ULEV_PANICS 0x01c ++#define CSI2_IRQ_MASK 0x020 ++#define CSI2_CTRL 0x024 ++#define CSI2_CH_CTRL(x) ((x) * 0x40 + 0x28) ++#define CSI2_CH_ADDR0(x) ((x) * 0x40 + 0x2c) ++#define CSI2_CH_ADDR1(x) ((x) * 0x40 + 0x3c) ++#define CSI2_CH_STRIDE(x) ((x) * 0x40 + 0x30) ++#define CSI2_CH_LENGTH(x) ((x) * 0x40 + 0x34) ++#define CSI2_CH_DEBUG(x) ((x) * 0x40 + 0x38) ++#define CSI2_CH_FRAME_SIZE(x) ((x) * 0x40 + 0x40) ++#define CSI2_CH_COMP_CTRL(x) ((x) * 0x40 + 0x44) ++#define CSI2_CH_FE_FRAME_ID(x) ((x) * 0x40 + 0x48) ++ ++/* CSI2_STATUS */ ++#define IRQ_FS(x) (BIT(0) << (x)) ++#define IRQ_FE(x) (BIT(4) << (x)) ++#define IRQ_FE_ACK(x) (BIT(8) << (x)) ++#define IRQ_LE(x) (BIT(12) << (x)) ++#define IRQ_LE_ACK(x) (BIT(16) << (x)) ++#define IRQ_CH_MASK(x) (IRQ_FS(x) | IRQ_FE(x) | IRQ_FE_ACK(x) | IRQ_LE(x) | IRQ_LE_ACK(x)) ++#define IRQ_OVERFLOW BIT(20) ++#define IRQ_DISCARD_OVERFLOW BIT(21) ++#define IRQ_DISCARD_LEN_LIMIT BIT(22) ++#define IRQ_DISCARD_UNMATCHED BIT(23) ++#define IRQ_DISCARD_INACTIVE BIT(24) ++ ++/* CSI2_CTRL */ ++#define EOP_IS_EOL BIT(0) ++ ++/* CSI2_CH_CTRL */ ++#define DMA_EN BIT(0) ++#define FORCE BIT(3) ++#define AUTO_ARM BIT(4) ++#define IRQ_EN_FS BIT(13) ++#define IRQ_EN_FE BIT(14) ++#define IRQ_EN_FE_ACK BIT(15) ++#define IRQ_EN_LE BIT(16) ++#define IRQ_EN_LE_ACK BIT(17) ++#define FLUSH_FE BIT(28) ++#define PACK_LINE BIT(29) ++#define PACK_BYTES BIT(30) ++#define CH_MODE_MASK GENMASK(2, 1) ++#define VC_MASK GENMASK(6, 5) ++#define DT_MASK GENMASK(12, 7) ++#define LC_MASK GENMASK(27, 18) ++ ++/* CHx_COMPRESSION_CONTROL */ ++#define COMP_OFFSET_MASK GENMASK(15, 0) ++#define COMP_SHIFT_MASK GENMASK(19, 16) ++#define COMP_MODE_MASK GENMASK(25, 24) ++ ++static inline u32 csi2_reg_read(struct csi2_device *csi2, u32 offset) ++{ ++ return readl(csi2->base + offset); ++} ++ ++static inline void csi2_reg_write(struct csi2_device *csi2, u32 offset, u32 val) ++{ ++ writel(val, csi2->base + offset); ++} ++ ++static inline void set_field(u32 *valp, u32 field, u32 mask) ++{ ++ u32 val = *valp; ++ ++ val &= ~mask; ++ val |= (field << __ffs(mask)) & mask; ++ *valp = val; ++} ++ ++static int csi2_regs_show(struct seq_file *s, void *data) ++{ ++ struct csi2_device *csi2 = s->private; ++ unsigned int i; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(csi2->v4l2_dev->dev); ++ if (ret) ++ return ret; ++ ++#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", csi2_reg_read(csi2, reg)) ++#define DUMP_CH(idx, reg) seq_printf(s, #reg "(%u) \t0x%08x\n", idx, csi2_reg_read(csi2, reg(idx))) ++ ++ DUMP(CSI2_STATUS); ++ DUMP(CSI2_DISCARDS_OVERFLOW); ++ DUMP(CSI2_DISCARDS_INACTIVE); ++ DUMP(CSI2_DISCARDS_UNMATCHED); ++ DUMP(CSI2_DISCARDS_LEN_LIMIT); ++ DUMP(CSI2_LLEV_PANICS); ++ DUMP(CSI2_ULEV_PANICS); ++ DUMP(CSI2_IRQ_MASK); ++ DUMP(CSI2_CTRL); ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; ++i) { ++ DUMP_CH(i, CSI2_CH_CTRL); ++ DUMP_CH(i, CSI2_CH_ADDR0); ++ DUMP_CH(i, CSI2_CH_ADDR1); ++ DUMP_CH(i, CSI2_CH_STRIDE); ++ DUMP_CH(i, CSI2_CH_LENGTH); ++ DUMP_CH(i, CSI2_CH_DEBUG); ++ DUMP_CH(i, CSI2_CH_FRAME_SIZE); ++ DUMP_CH(i, CSI2_CH_COMP_CTRL); ++ DUMP_CH(i, CSI2_CH_FE_FRAME_ID); ++ } ++ ++#undef DUMP ++#undef DUMP_CH ++ ++ pm_runtime_put(csi2->v4l2_dev->dev); ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(csi2_regs); ++ ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci) ++{ ++ unsigned int i; ++ u32 status; ++ ++ status = csi2_reg_read(csi2, CSI2_STATUS); ++ csi2_dbg_irq("ISR: STA: 0x%x\n", status); ++ ++ /* Write value back to clear the interrupts */ ++ csi2_reg_write(csi2, CSI2_STATUS, status); ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; i++) { ++ u32 dbg; ++ ++ if ((status & IRQ_CH_MASK(i)) == 0) ++ continue; ++ ++ dbg = csi2_reg_read(csi2, CSI2_CH_DEBUG(i)); ++ ++ csi2_dbg_irq("ISR: [%u], %s%s%s%s%s frame: %u line: %u\n", i, ++ (status & IRQ_FS(i)) ? "FS " : "", ++ (status & IRQ_FE(i)) ? "FE " : "", ++ (status & IRQ_FE_ACK(i)) ? "FE_ACK " : "", ++ (status & IRQ_LE(i)) ? "LE " : "", ++ (status & IRQ_LE_ACK(i)) ? "LE_ACK " : "", ++ dbg >> 16, ++ csi2->num_lines[i] ? ++ ((dbg & 0xffff) % csi2->num_lines[i]) : ++ 0); ++ ++ sof[i] = !!(status & IRQ_FS(i)); ++ eof[i] = !!(status & IRQ_FE_ACK(i)); ++ lci[i] = !!(status & IRQ_LE_ACK(i)); ++ } ++} ++ ++void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, ++ dma_addr_t dmaaddr, unsigned int stride, unsigned int size) ++{ ++ u64 addr = dmaaddr; ++ /* ++ * ADDRESS0 must be written last as it triggers the double buffering ++ * mechanism for all buffer registers within the hardware. ++ */ ++ addr >>= 4; ++ csi2_reg_write(csi2, CSI2_CH_LENGTH(channel), size >> 4); ++ csi2_reg_write(csi2, CSI2_CH_STRIDE(channel), stride >> 4); ++ csi2_reg_write(csi2, CSI2_CH_ADDR1(channel), addr >> 32); ++ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), addr & 0xffffffff); ++} ++ ++void csi2_set_compression(struct csi2_device *csi2, unsigned int channel, ++ enum csi2_compression_mode mode, unsigned int shift, ++ unsigned int offset) ++{ ++ u32 compression = 0; ++ ++ set_field(&compression, COMP_OFFSET_MASK, offset); ++ set_field(&compression, COMP_SHIFT_MASK, shift); ++ set_field(&compression, COMP_MODE_MASK, mode); ++ csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression); ++} ++ ++void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, ++ u16 dt, enum csi2_mode mode, bool auto_arm, ++ bool pack_bytes, unsigned int width, ++ unsigned int height) ++{ ++ u32 ctrl; ++ ++ csi2_dbg("%s [%u]\n", __func__, channel); ++ ++ /* ++ * Disable the channel, but ensure N != 0! Otherwise we end up with a ++ * spurious LE + LE_ACK interrupt when re-enabling the channel. ++ */ ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0x100 << __ffs(LC_MASK)); ++ csi2_reg_write(csi2, CSI2_CH_DEBUG(channel), 0); ++ csi2_reg_write(csi2, CSI2_STATUS, IRQ_CH_MASK(channel)); ++ ++ /* Enable channel and FS/FE/LE interrupts. */ ++ ctrl = DMA_EN | IRQ_EN_FS | IRQ_EN_FE_ACK | IRQ_EN_LE_ACK | PACK_LINE; ++ /* PACK_BYTES ensures no striding for embedded data. */ ++ if (pack_bytes) ++ ctrl |= PACK_BYTES; ++ ++ if (auto_arm) ++ ctrl |= AUTO_ARM; ++ ++ if (width && height) { ++ int line_int_freq = height >> 2; ++ ++ line_int_freq = min(max(0x80, line_int_freq), 0x3ff); ++ set_field(&ctrl, line_int_freq, LC_MASK); ++ set_field(&ctrl, mode, CH_MODE_MASK); ++ csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), ++ (height << 16) | width); ++ } else { ++ /* ++ * Do not disable line interrupts for the embedded data channel, ++ * set it to the maximum value. This avoids spamming the ISR ++ * with spurious line interrupts. ++ */ ++ set_field(&ctrl, 0x3ff, LC_MASK); ++ set_field(&ctrl, 0x00, CH_MODE_MASK); ++ } ++ ++ set_field(&ctrl, dt, DT_MASK); ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl); ++ csi2->num_lines[channel] = height; ++} ++ ++void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel) ++{ ++ csi2_dbg("%s [%u]\n", __func__, channel); ++ ++ /* Channel disable. Use FORCE to allow stopping mid-frame. */ ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ++ (0x100 << __ffs(LC_MASK)) | FORCE); ++ /* Latch the above change by writing to the ADDR0 register. */ ++ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0); ++ /* Write this again, the HW needs it! */ ++ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0); ++} ++ ++void csi2_open_rx(struct csi2_device *csi2) ++{ ++ dphy_start(&csi2->dphy); ++ ++ if (!csi2->multipacket_line) ++ csi2_reg_write(csi2, CSI2_CTRL, EOP_IS_EOL); ++} ++ ++void csi2_close_rx(struct csi2_device *csi2) ++{ ++ dphy_stop(&csi2->dphy); ++} ++ ++static struct csi2_device *to_csi2_device(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct csi2_device, sd); ++} ++ ++static int csi2_init_cfg(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ ++ for (unsigned int i = 0; i < CSI2_NUM_CHANNELS; ++i) { ++ const struct v4l2_mbus_framefmt *def_fmt; ++ ++ /* CSI2_CH1_EMBEDDED */ ++ if (i == 1) ++ def_fmt = &cfe_default_meta_format; ++ else ++ def_fmt = &cfe_default_format; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, i); ++ *fmt = *def_fmt; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, i + CSI2_NUM_CHANNELS); ++ *fmt = *def_fmt; ++ } ++ ++ return 0; ++} ++ ++static int csi2_pad_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ const struct cfe_fmt *cfe_fmt; ++ ++ /* TODO: format validation */ ++ ++ cfe_fmt = find_format_by_code(format->format.code); ++ if (!cfe_fmt) ++ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ ++ format->format.code = cfe_fmt->code; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ *fmt = format->format; ++ ++ if (format->pad < CSI2_NUM_CHANNELS) { ++ /* Propagate to the source pad */ ++ fmt = v4l2_subdev_get_pad_format(sd, state, ++ format->pad + CSI2_NUM_CHANNELS); ++ *fmt = format->format; ++ } ++ ++ return 0; ++} ++ ++static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link, ++ struct v4l2_subdev_format *source_fmt, ++ struct v4l2_subdev_format *sink_fmt) ++{ ++ struct csi2_device *csi2 = to_csi2_device(sd); ++ ++ csi2_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index); ++ ++ if ((link->source->entity == &csi2->sd.entity && ++ link->source->index == 1) || ++ (link->sink->entity == &csi2->sd.entity && ++ link->sink->index == 1)) { ++ csi2_dbg("Ignore metadata pad for now\n"); ++ return 0; ++ } ++ ++ /* The width, height and code must match. */ ++ if (source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.code != sink_fmt->format.code) { ++ csi2_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", ++ __func__, ++ source_fmt->format.width, source_fmt->format.height, ++ source_fmt->format.code, ++ sink_fmt->format.width, sink_fmt->format.height, ++ sink_fmt->format.code); ++ return -EPIPE; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops csi2_subdev_pad_ops = { ++ .init_cfg = csi2_init_cfg, ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = csi2_pad_set_fmt, ++ .link_validate = csi2_link_validate, ++}; ++ ++static const struct media_entity_operations csi2_entity_ops = { ++ .link_validate = v4l2_subdev_link_validate, ++}; ++ ++static const struct v4l2_subdev_ops csi2_subdev_ops = { ++ .pad = &csi2_subdev_pad_ops, ++}; ++ ++int csi2_init(struct csi2_device *csi2, struct dentry *debugfs) ++{ ++ unsigned int i, ret; ++ ++ csi2->dphy.dev = csi2->v4l2_dev->dev; ++ dphy_probe(&csi2->dphy); ++ ++ debugfs_create_file("csi2_regs", 0444, debugfs, csi2, &csi2_regs_fops); ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS * 2; i++) ++ csi2->pad[i].flags = i < CSI2_NUM_CHANNELS ? ++ MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; ++ ++ ret = media_entity_pads_init(&csi2->sd.entity, ARRAY_SIZE(csi2->pad), ++ csi2->pad); ++ if (ret) ++ return ret; ++ ++ /* Initialize subdev */ ++ v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops); ++ csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; ++ csi2->sd.entity.ops = &csi2_entity_ops; ++ csi2->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ csi2->sd.owner = THIS_MODULE; ++ snprintf(csi2->sd.name, sizeof(csi2->sd.name), "csi2"); ++ ++ ret = v4l2_subdev_init_finalize(&csi2->sd); ++ if (ret) ++ goto err_entity_cleanup; ++ ++ ret = v4l2_device_register_subdev(csi2->v4l2_dev, &csi2->sd); ++ if (ret) { ++ csi2_err("Failed register csi2 subdev (%d)\n", ret); ++ goto err_subdev_cleanup; ++ } ++ ++ return 0; ++ ++err_subdev_cleanup: ++ v4l2_subdev_cleanup(&csi2->sd); ++err_entity_cleanup: ++ media_entity_cleanup(&csi2->sd.entity); ++ ++ return ret; ++} ++ ++void csi2_uninit(struct csi2_device *csi2) ++{ ++ v4l2_device_unregister_subdev(&csi2->sd); ++ v4l2_subdev_cleanup(&csi2->sd); ++ media_entity_cleanup(&csi2->sd.entity); ++} +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -0,0 +1,75 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 CSI-2 driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _RP1_CSI2_ ++#define _RP1_CSI2_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "dphy.h" ++ ++#define CSI2_NUM_CHANNELS 4 ++ ++enum csi2_mode { ++ CSI2_MODE_NORMAL, ++ CSI2_MODE_REMAP, ++ CSI2_MODE_COMPRESSED, ++ CSI2_MODE_FE_STREAMING ++}; ++ ++enum csi2_compression_mode { ++ CSI2_COMPRESSION_DELTA = 1, ++ CSI2_COMPRESSION_SIMPLE = 2, ++ CSI2_COMPRESSION_COMBINED = 3, ++}; ++ ++struct csi2_cfg { ++ u16 width; ++ u16 height; ++ u32 stride; ++ u32 buffer_size; ++}; ++ ++struct csi2_device { ++ /* Parent V4l2 device */ ++ struct v4l2_device *v4l2_dev; ++ ++ void __iomem *base; ++ ++ struct dphy_data dphy; ++ ++ enum v4l2_mbus_type bus_type; ++ unsigned int bus_flags; ++ u32 active_data_lanes; ++ bool multipacket_line; ++ unsigned int num_lines[CSI2_NUM_CHANNELS]; ++ ++ struct media_pad pad[CSI2_NUM_CHANNELS * 2]; ++ struct v4l2_subdev sd; ++}; ++ ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci); ++void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, ++ dma_addr_t dmaaddr, unsigned int stride, ++ unsigned int size); ++void csi2_set_compression(struct csi2_device *csi2, unsigned int channel, ++ enum csi2_compression_mode mode, unsigned int shift, ++ unsigned int offset); ++void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, ++ u16 dt, enum csi2_mode mode, bool auto_arm, ++ bool pack_bytes, unsigned int width, ++ unsigned int height); ++void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel); ++void csi2_open_rx(struct csi2_device *csi2); ++void csi2_close_rx(struct csi2_device *csi2); ++int csi2_init(struct csi2_device *csi2, struct dentry *debugfs); ++void csi2_uninit(struct csi2_device *csi2); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c +@@ -0,0 +1,177 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RP1 CSI-2 Driver ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "dphy.h" ++ ++#define dphy_dbg(fmt, arg...) dev_dbg(dphy->dev, fmt, ##arg) ++#define dphy_info(fmt, arg...) dev_info(dphy->dev, fmt, ##arg) ++#define dphy_err(fmt, arg...) dev_err(dphy->dev, fmt, ##arg) ++ ++/* DW dphy Host registers */ ++#define VERSION 0x000 ++#define N_LANES 0x004 ++#define RESETN 0x008 ++#define PHY_SHUTDOWNZ 0x040 ++#define PHY_RSTZ 0x044 ++#define PHY_RX 0x048 ++#define PHY_STOPSTATE 0x04c ++#define PHY_TST_CTRL0 0x050 ++#define PHY_TST_CTRL1 0x054 ++#define PHY2_TST_CTRL0 0x058 ++#define PHY2_TST_CTRL1 0x05c ++ ++/* DW dphy Host Transactions */ ++#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44 ++#define DPHY_PLL_INPUT_DIV_OFFSET 0x17 ++#define DPHY_PLL_LOOP_DIV_OFFSET 0x18 ++#define DPHY_PLL_DIV_CTRL_OFFSET 0x19 ++ ++static u32 dw_csi2_host_read(struct dphy_data *dphy, u32 offset) ++{ ++ return readl(dphy->base + offset); ++} ++ ++static void dw_csi2_host_write(struct dphy_data *dphy, u32 offset, u32 data) ++{ ++ writel(data, dphy->base + offset); ++} ++ ++static void set_tstclr(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl0 = dw_csi2_host_read(dphy, PHY_TST_CTRL0); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL0, (ctrl0 & ~1) | val); ++} ++ ++static void set_tstclk(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl0 = dw_csi2_host_read(dphy, PHY_TST_CTRL0); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL0, (ctrl0 & ~2) | (val << 1)); ++} ++ ++static uint8_t get_tstdout(struct dphy_data *dphy) ++{ ++ u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1); ++ ++ return ((ctrl1 >> 8) & 0xff); ++} ++ ++static void set_testen(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL1, ++ (ctrl1 & ~(1 << 16)) | (val << 16)); ++} ++ ++static void set_testdin(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL1, (ctrl1 & ~0xff) | val); ++} ++ ++static uint8_t dphy_transaction(struct dphy_data *dphy, u8 test_code, ++ uint8_t test_data) ++{ ++ /* See page 101 of the MIPI DPHY databook. */ ++ set_tstclk(dphy, 1); ++ set_testen(dphy, 0); ++ set_testdin(dphy, test_code); ++ set_testen(dphy, 1); ++ set_tstclk(dphy, 0); ++ set_testen(dphy, 0); ++ set_testdin(dphy, test_data); ++ set_tstclk(dphy, 1); ++ return get_tstdout(dphy); ++} ++ ++static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t freq_mhz) ++{ ++ /* See Table 5-1 on page 65 of dphy databook */ ++ static const u16 hsfreqrange_table[][2] = { ++ { 89, 0b000000 }, { 99, 0b010000 }, { 109, 0b100000 }, ++ { 129, 0b000001 }, { 139, 0b010001 }, { 149, 0b100001 }, ++ { 169, 0b000010 }, { 179, 0b010010 }, { 199, 0b100010 }, ++ { 219, 0b000011 }, { 239, 0b010011 }, { 249, 0b100011 }, ++ { 269, 0b000100 }, { 299, 0b010100 }, { 329, 0b000101 }, ++ { 359, 0b010101 }, { 399, 0b100101 }, { 449, 0b000110 }, ++ { 499, 0b010110 }, { 549, 0b000111 }, { 599, 0b010111 }, ++ { 649, 0b001000 }, { 699, 0b011000 }, { 749, 0b001001 }, ++ { 799, 0b011001 }, { 849, 0b101001 }, { 899, 0b111001 }, ++ { 949, 0b001010 }, { 999, 0b011010 }, { 1049, 0b101010 }, ++ { 1099, 0b111010 }, { 1149, 0b001011 }, { 1199, 0b011011 }, ++ { 1249, 0b101011 }, { 1299, 0b111011 }, { 1349, 0b001100 }, ++ { 1399, 0b011100 }, { 1449, 0b101100 }, { 1500, 0b111100 }, ++ }; ++ unsigned int i; ++ ++ if (freq_mhz < 80 || freq_mhz > 1500) ++ dphy_err("DPHY: Frequency %u MHz out of range\n", freq_mhz); ++ ++ for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) { ++ if (freq_mhz <= hsfreqrange_table[i][0]) ++ break; ++ } ++ ++ dphy_transaction(dphy, DPHY_HS_RX_CTRL_LANE0_OFFSET, ++ hsfreqrange_table[i][1] << 1); ++} ++ ++static void dphy_init(struct dphy_data *dphy) ++{ ++ dw_csi2_host_write(dphy, PHY_RSTZ, 0); ++ dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 0); ++ set_tstclk(dphy, 1); ++ set_testen(dphy, 0); ++ set_tstclr(dphy, 1); ++ usleep_range(15, 20); ++ set_tstclr(dphy, 0); ++ usleep_range(15, 20); ++ ++ dphy_set_hsfreqrange(dphy, dphy->dphy_freq); ++ ++ usleep_range(5, 10); ++ dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 1); ++ usleep_range(5, 10); ++ dw_csi2_host_write(dphy, PHY_RSTZ, 1); ++} ++ ++void dphy_start(struct dphy_data *dphy) ++{ ++ dw_csi2_host_write(dphy, N_LANES, (dphy->num_lanes - 1)); ++ dphy_init(dphy); ++ dw_csi2_host_write(dphy, RESETN, 0xffffffff); ++ usleep_range(10, 50); ++} ++ ++void dphy_stop(struct dphy_data *dphy) ++{ ++ /* Set only one lane (lane 0) as active (ON) */ ++ dw_csi2_host_write(dphy, N_LANES, 0); ++ dw_csi2_host_write(dphy, RESETN, 0); ++} ++ ++void dphy_probe(struct dphy_data *dphy) ++{ ++ u32 host_ver; ++ u8 host_ver_major, host_ver_minor; ++ ++ host_ver = dw_csi2_host_read(dphy, VERSION); ++ host_ver_major = (u8)((host_ver >> 24) - '0'); ++ host_ver_minor = (u8)((host_ver >> 16) - '0'); ++ host_ver_minor = host_ver_minor * 10; ++ host_ver_minor += (u8)((host_ver >> 8) - '0'); ++ ++ dphy_info("DW dphy Host HW v%u.%u\n", host_ver_major, host_ver_minor); ++} +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++ ++#ifndef _RP1_DPHY_ ++#define _RP1_DPHY_ ++ ++#include ++#include ++ ++struct dphy_data { ++ struct device *dev; ++ ++ void __iomem *base; ++ ++ u32 dphy_freq; ++ u32 num_lanes; ++}; ++ ++void dphy_probe(struct dphy_data *dphy); ++void dphy_start(struct dphy_data *dphy); ++void dphy_stop(struct dphy_data *dphy); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h +@@ -0,0 +1,69 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP common definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_COMMON_H_ ++#define _PISP_COMMON_H_ ++ ++#include "pisp_types.h" ++ ++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]; ++}; ++ ++struct pisp_wbg_config { ++ u16 gain_r; ++ u16 gain_g; ++ u16 gain_b; ++ u8 pad[2]; ++}; ++ ++struct pisp_compress_config { ++ /* value subtracted from incoming data */ ++ u16 offset; ++ u8 pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ u8 mode; ++}; ++ ++struct pisp_decompress_config { ++ /* value added to reconstructed data */ ++ u16 offset; ++ u8 pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ u8 mode; ++}; ++ ++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; ++}; ++ ++#endif /* _PISP_COMMON_H_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -0,0 +1,563 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * PiSP Front End driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "pisp_fe.h" ++#include "cfe.h" ++ ++#define FE_VERSION 0x000 ++#define FE_CONTROL 0x004 ++#define FE_STATUS 0x008 ++#define FE_FRAME_STATUS 0x00c ++#define FE_ERROR_STATUS 0x010 ++#define FE_OUTPUT_STATUS 0x014 ++#define FE_INT_EN 0x018 ++#define FE_INT_STATUS 0x01c ++ ++/* CONTROL */ ++#define FE_CONTROL_QUEUE BIT(0) ++#define FE_CONTROL_ABORT BIT(1) ++#define FE_CONTROL_RESET BIT(2) ++#define FE_CONTROL_LATCH_REGS BIT(3) ++ ++/* INT_EN / INT_STATUS */ ++#define FE_INT_EOF BIT(0) ++#define FE_INT_SOF BIT(1) ++#define FE_INT_LINES0 BIT(8) ++#define FE_INT_LINES1 BIT(9) ++#define FE_INT_STATS BIT(16) ++#define FE_INT_QREADY BIT(24) ++ ++/* STATUS */ ++#define FE_STATUS_QUEUED BIT(0) ++#define FE_STATUS_WAITING BIT(1) ++#define FE_STATUS_ACTIVE BIT(2) ++ ++#define PISP_FE_CONFIG_BASE_OFFSET 0x0040 ++ ++#define PISP_FE_ENABLE_STATS_CLUSTER \ ++ (PISP_FE_ENABLE_STATS_CROP | PISP_FE_ENABLE_DECIMATE | \ ++ PISP_FE_ENABLE_BLC | PISP_FE_ENABLE_CDAF_STATS | \ ++ PISP_FE_ENABLE_AWB_STATS | PISP_FE_ENABLE_RGBY | \ ++ PISP_FE_ENABLE_LSC | PISP_FE_ENABLE_AGC_STATS) ++ ++#define PISP_FE_ENABLE_OUTPUT_CLUSTER(i) \ ++ ((PISP_FE_ENABLE_CROP0 | PISP_FE_ENABLE_DOWNSCALE0 | \ ++ PISP_FE_ENABLE_COMPRESS0 | PISP_FE_ENABLE_OUTPUT0) << (4 * (i))) ++ ++struct pisp_fe_config_param { ++ u32 dirty_flags; ++ u32 dirty_flags_extra; ++ size_t offset; ++ size_t size; ++}; ++ ++static const struct pisp_fe_config_param pisp_fe_config_map[] = { ++ /* *_dirty_flag_extra types */ ++ { 0, PISP_FE_DIRTY_GLOBAL, offsetof(struct pisp_fe_config, global), ++ sizeof(struct pisp_fe_global_config) }, ++ { 0, PISP_FE_DIRTY_FLOATING, offsetof(struct pisp_fe_config, floating_stats), ++ sizeof(struct pisp_fe_floating_stats_config) }, ++ { 0, PISP_FE_DIRTY_OUTPUT_AXI, offsetof(struct pisp_fe_config, output_axi), ++ sizeof(struct pisp_fe_output_axi_config) }, ++ /* *_dirty_flag types */ ++ { PISP_FE_ENABLE_INPUT, 0, offsetof(struct pisp_fe_config, input), ++ sizeof(struct pisp_fe_input_config) }, ++ { PISP_FE_ENABLE_DECOMPRESS, 0, offsetof(struct pisp_fe_config, decompress), ++ sizeof(struct pisp_decompress_config) }, ++ { PISP_FE_ENABLE_DECOMPAND, 0, offsetof(struct pisp_fe_config, decompand), ++ sizeof(struct pisp_fe_decompand_config) }, ++ { PISP_FE_ENABLE_BLA, 0, offsetof(struct pisp_fe_config, bla), ++ sizeof(struct pisp_bla_config) }, ++ { PISP_FE_ENABLE_DPC, 0, offsetof(struct pisp_fe_config, dpc), ++ sizeof(struct pisp_fe_dpc_config) }, ++ { PISP_FE_ENABLE_STATS_CROP, 0, offsetof(struct pisp_fe_config, stats_crop), ++ sizeof(struct pisp_fe_crop_config) }, ++ { PISP_FE_ENABLE_BLC, 0, offsetof(struct pisp_fe_config, blc), ++ sizeof(struct pisp_bla_config) }, ++ { PISP_FE_ENABLE_CDAF_STATS, 0, offsetof(struct pisp_fe_config, cdaf_stats), ++ sizeof(struct pisp_fe_cdaf_stats_config) }, ++ { PISP_FE_ENABLE_AWB_STATS, 0, offsetof(struct pisp_fe_config, awb_stats), ++ sizeof(struct pisp_fe_awb_stats_config) }, ++ { PISP_FE_ENABLE_RGBY, 0, offsetof(struct pisp_fe_config, rgby), ++ sizeof(struct pisp_fe_rgby_config) }, ++ { PISP_FE_ENABLE_LSC, 0, offsetof(struct pisp_fe_config, lsc), ++ sizeof(struct pisp_fe_lsc_config) }, ++ { PISP_FE_ENABLE_AGC_STATS, 0, offsetof(struct pisp_fe_config, agc_stats), ++ sizeof(struct pisp_agc_statistics) }, ++ { PISP_FE_ENABLE_CROP0, 0, offsetof(struct pisp_fe_config, ch[0].crop), ++ sizeof(struct pisp_fe_crop_config) }, ++ { PISP_FE_ENABLE_DOWNSCALE0, 0, offsetof(struct pisp_fe_config, ch[0].downscale), ++ sizeof(struct pisp_fe_downscale_config) }, ++ { PISP_FE_ENABLE_COMPRESS0, 0, offsetof(struct pisp_fe_config, ch[0].compress), ++ sizeof(struct pisp_compress_config) }, ++ { PISP_FE_ENABLE_OUTPUT0, 0, offsetof(struct pisp_fe_config, ch[0].output), ++ sizeof(struct pisp_fe_output_config) }, ++ { PISP_FE_ENABLE_CROP1, 0, offsetof(struct pisp_fe_config, ch[1].crop), ++ sizeof(struct pisp_fe_crop_config) }, ++ { PISP_FE_ENABLE_DOWNSCALE1, 0, offsetof(struct pisp_fe_config, ch[1].downscale), ++ sizeof(struct pisp_fe_downscale_config) }, ++ { PISP_FE_ENABLE_COMPRESS1, 0, offsetof(struct pisp_fe_config, ch[1].compress), ++ sizeof(struct pisp_compress_config) }, ++ { PISP_FE_ENABLE_OUTPUT1, 0, offsetof(struct pisp_fe_config, ch[1].output), ++ sizeof(struct pisp_fe_output_config) }, ++}; ++ ++#define pisp_fe_dbg_irq(fmt, arg...) \ ++ do { \ ++ if (cfe_debug_irq) \ ++ dev_dbg(fe->v4l2_dev->dev, fmt, ##arg); \ ++ } while (0) ++#define pisp_fe_dbg(fmt, arg...) dev_dbg(fe->v4l2_dev->dev, fmt, ##arg) ++#define pisp_fe_info(fmt, arg...) dev_info(fe->v4l2_dev->dev, fmt, ##arg) ++#define pisp_fe_err(fmt, arg...) dev_err(fe->v4l2_dev->dev, fmt, ##arg) ++ ++static inline u32 pisp_fe_reg_read(struct pisp_fe_device *fe, u32 offset) ++{ ++ return readl(fe->base + offset); ++} ++ ++static inline void pisp_fe_reg_write(struct pisp_fe_device *fe, u32 offset, ++ u32 val) ++{ ++ writel(val, fe->base + offset); ++} ++ ++static inline void pisp_fe_reg_write_relaxed(struct pisp_fe_device *fe, u32 offset, ++ u32 val) ++{ ++ writel_relaxed(val, fe->base + offset); ++} ++ ++static int pisp_regs_show(struct seq_file *s, void *data) ++{ ++ struct pisp_fe_device *fe = s->private; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(fe->v4l2_dev->dev); ++ if (ret) ++ return ret; ++ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS); ++ ++#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", pisp_fe_reg_read(fe, reg)) ++ DUMP(FE_VERSION); ++ DUMP(FE_CONTROL); ++ DUMP(FE_STATUS); ++ DUMP(FE_FRAME_STATUS); ++ DUMP(FE_ERROR_STATUS); ++ DUMP(FE_OUTPUT_STATUS); ++ DUMP(FE_INT_EN); ++ DUMP(FE_INT_STATUS); ++#undef DUMP ++ ++ pm_runtime_put(fe->v4l2_dev->dev); ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(pisp_regs); ++ ++static void pisp_config_write(struct pisp_fe_device *fe, ++ struct pisp_fe_config *config, ++ unsigned int start_offset, ++ unsigned int size) ++{ ++ const unsigned int max_offset = ++ offsetof(struct pisp_fe_config, ch[PISP_FE_NUM_OUTPUTS]); ++ unsigned int i, end_offset; ++ u32 *cfg = (u32 *)config; ++ ++ start_offset = min(start_offset, max_offset); ++ end_offset = min(start_offset + size, max_offset); ++ ++ cfg += start_offset >> 2; ++ for (i = start_offset; i < end_offset; i += 4, cfg++) ++ pisp_fe_reg_write_relaxed(fe, PISP_FE_CONFIG_BASE_OFFSET + i, ++ *cfg); ++} ++ ++void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof) ++{ ++ u32 status, int_status, out_status, frame_status, error_status; ++ unsigned int i; ++ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS); ++ status = pisp_fe_reg_read(fe, FE_STATUS); ++ out_status = pisp_fe_reg_read(fe, FE_OUTPUT_STATUS); ++ frame_status = pisp_fe_reg_read(fe, FE_FRAME_STATUS); ++ error_status = pisp_fe_reg_read(fe, FE_ERROR_STATUS); ++ ++ int_status = pisp_fe_reg_read(fe, FE_INT_STATUS); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, int_status); ++ ++ pisp_fe_dbg_irq("%s: status 0x%x out 0x%x frame 0x%x error 0x%x int 0x%x\n", ++ __func__, status, out_status, frame_status, error_status, ++ int_status); ++ ++ /* We do not report interrupts for the input/stream pad. */ ++ for (i = 0; i < FE_NUM_PADS - 1; i++) { ++ sof[i] = !!(int_status & FE_INT_SOF); ++ eof[i] = !!(int_status & FE_INT_EOF); ++ } ++} ++ ++static bool pisp_fe_validate_output(struct pisp_fe_config const *cfg, ++ unsigned int c, struct v4l2_format const *f) ++{ ++ unsigned int wbytes; ++ ++ wbytes = cfg->ch[c].output.format.width; ++ if (cfg->ch[c].output.format.format & PISP_IMAGE_FORMAT_BPS_MASK) ++ wbytes *= 2; ++ ++ /* Check output image dimensions are nonzero and not too big */ ++ if (cfg->ch[c].output.format.width < 2 || ++ cfg->ch[c].output.format.height < 2 || ++ cfg->ch[c].output.format.height > f->fmt.pix.height || ++ cfg->ch[c].output.format.stride > f->fmt.pix.bytesperline || ++ wbytes > f->fmt.pix.bytesperline) ++ return false; ++ ++ /* Check for zero-sized crops, which could cause lockup */ ++ if ((cfg->global.enables & PISP_FE_ENABLE_CROP(c)) && ++ ((cfg->ch[c].crop.offset_x >= (cfg->input.format.width & ~1) || ++ cfg->ch[c].crop.offset_y >= cfg->input.format.height || ++ cfg->ch[c].crop.width < 2 || ++ cfg->ch[c].crop.height < 2))) ++ return false; ++ ++ if ((cfg->global.enables & PISP_FE_ENABLE_DOWNSCALE(c)) && ++ (cfg->ch[c].downscale.output_width < 2 || ++ cfg->ch[c].downscale.output_height < 2)) ++ return false; ++ ++ return true; ++} ++ ++static bool pisp_fe_validate_stats(struct pisp_fe_config const *cfg) ++{ ++ /* Check for zero-sized crop, which could cause lockup */ ++ return (!(cfg->global.enables & PISP_FE_ENABLE_STATS_CROP) || ++ (cfg->stats_crop.offset_x < (cfg->input.format.width & ~1) && ++ cfg->stats_crop.offset_y < cfg->input.format.height && ++ cfg->stats_crop.width >= 2 && ++ cfg->stats_crop.height >= 2)); ++} ++ ++int pisp_fe_validate_config(struct pisp_fe_device *fe, ++ struct pisp_fe_config *cfg, ++ struct v4l2_format const *f0, ++ struct v4l2_format const *f1) ++{ ++ unsigned int i; ++ ++ /* ++ * Check the input is enabled, streaming and has nonzero size; ++ * to avoid cases where the hardware might lock up or try to ++ * read inputs from memory (which this driver doesn't support). ++ */ ++ if (!(cfg->global.enables & PISP_FE_ENABLE_INPUT) || ++ cfg->input.streaming != 1 || cfg->input.format.width < 2 || ++ cfg->input.format.height < 2) { ++ pisp_fe_err("%s: Input config not valid", __func__); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < PISP_FE_NUM_OUTPUTS; i++) { ++ if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) { ++ if (cfg->global.enables & ++ PISP_FE_ENABLE_OUTPUT_CLUSTER(i)) { ++ pisp_fe_err("%s: Output %u not valid", ++ __func__, i); ++ return -EINVAL; ++ } ++ continue; ++ } ++ ++ if (!pisp_fe_validate_output(cfg, i, i ? f1 : f0)) ++ return -EINVAL; ++ } ++ ++ if ((cfg->global.enables & PISP_FE_ENABLE_STATS_CLUSTER) && ++ !pisp_fe_validate_stats(cfg)) { ++ pisp_fe_err("%s: Stats config not valid", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs, ++ struct pisp_fe_config *cfg) ++{ ++ unsigned int i; ++ u64 addr; ++ u32 status; ++ ++ /* ++ * Check output buffers exist and outputs are correctly configured. ++ * If valid, set the buffer's DMA address; otherwise disable. ++ */ ++ for (i = 0; i < PISP_FE_NUM_OUTPUTS; i++) { ++ struct vb2_buffer *buf = vb2_bufs[FE_OUTPUT0_PAD + i]; ++ ++ if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) ++ continue; ++ ++ addr = vb2_dma_contig_plane_dma_addr(buf, 0); ++ cfg->output_buffer[i].addr_lo = addr & 0xffffffff; ++ cfg->output_buffer[i].addr_hi = addr >> 32; ++ } ++ ++ if (vb2_bufs[FE_STATS_PAD]) { ++ addr = vb2_dma_contig_plane_dma_addr(vb2_bufs[FE_STATS_PAD], 0); ++ cfg->stats_buffer.addr_lo = addr & 0xffffffff; ++ cfg->stats_buffer.addr_hi = addr >> 32; ++ } ++ ++ /* Set up ILINES interrupts 3/4 of the way down each output */ ++ cfg->ch[0].output.ilines = ++ max(0x80u, (3u * cfg->ch[0].output.format.height) >> 2); ++ cfg->ch[1].output.ilines = ++ max(0x80u, (3u * cfg->ch[1].output.format.height) >> 2); ++ ++ /* ++ * The hardware must have consumed the previous config by now. ++ * This read of status also serves as a memory barrier before the ++ * sequence of relaxed writes which follow. ++ */ ++ status = pisp_fe_reg_read(fe, FE_STATUS); ++ pisp_fe_dbg_irq("%s: status = 0x%x\n", __func__, status); ++ if (WARN_ON(status & FE_STATUS_QUEUED)) ++ return; ++ ++ /* ++ * Unconditionally write buffers, global and input parameters. ++ * Write cropping and output parameters whenever they are enabled. ++ * Selectively write other parameters that have been marked as ++ * changed through the dirty flags. ++ */ ++ pisp_config_write(fe, cfg, 0, ++ offsetof(struct pisp_fe_config, decompress)); ++ cfg->dirty_flags_extra &= ~PISP_FE_DIRTY_GLOBAL; ++ cfg->dirty_flags &= ~PISP_FE_ENABLE_INPUT; ++ cfg->dirty_flags |= (cfg->global.enables & ++ (PISP_FE_ENABLE_STATS_CROP | ++ PISP_FE_ENABLE_OUTPUT_CLUSTER(0) | ++ PISP_FE_ENABLE_OUTPUT_CLUSTER(1))); ++ for (i = 0; i < ARRAY_SIZE(pisp_fe_config_map); i++) { ++ const struct pisp_fe_config_param *p = &pisp_fe_config_map[i]; ++ ++ if (cfg->dirty_flags & p->dirty_flags || ++ cfg->dirty_flags_extra & p->dirty_flags_extra) ++ pisp_config_write(fe, cfg, p->offset, p->size); ++ } ++ ++ /* This final non-relaxed write serves as a memory barrier */ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_QUEUE); ++} ++ ++void pisp_fe_start(struct pisp_fe_device *fe) ++{ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_RESET); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++ pisp_fe_reg_write(fe, FE_INT_EN, FE_INT_EOF | FE_INT_SOF | FE_INT_LINES0 | FE_INT_LINES1); ++ fe->inframe_count = 0; ++} ++ ++void pisp_fe_stop(struct pisp_fe_device *fe) ++{ ++ pisp_fe_reg_write(fe, FE_INT_EN, 0); ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_ABORT); ++ usleep_range(1000, 2000); ++ WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++} ++ ++static struct pisp_fe_device *to_pisp_fe_device(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct pisp_fe_device, sd); ++} ++ ++static int pisp_fe_init_cfg(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_STREAM_PAD); ++ *fmt = cfe_default_format; ++ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_CONFIG_PAD); ++ *fmt = cfe_default_meta_format; ++ fmt->code = MEDIA_BUS_FMT_PISP_FE_CONFIG; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT0_PAD); ++ *fmt = cfe_default_format; ++ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT1_PAD); ++ *fmt = cfe_default_format; ++ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_STATS_PAD); ++ *fmt = cfe_default_meta_format; ++ fmt->code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ ++ return 0; ++} ++ ++static int pisp_fe_pad_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ const struct cfe_fmt *cfe_fmt; ++ ++ /* TODO: format propagation to source pads */ ++ /* TODO: format validation */ ++ ++ switch (format->pad) { ++ case FE_STREAM_PAD: ++ case FE_OUTPUT0_PAD: ++ case FE_OUTPUT1_PAD: ++ cfe_fmt = find_format_by_code(format->format.code); ++ if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) ++ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ ++ format->format.code = cfe_fmt->code; ++ ++ break; ++ ++ case FE_CONFIG_PAD: ++ format->format.code = MEDIA_BUS_FMT_PISP_FE_CONFIG; ++ break; ++ ++ case FE_STATS_PAD: ++ format->format.code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ break; ++ } ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ *fmt = format->format; ++ ++ return 0; ++} ++ ++static int pisp_fe_link_validate(struct v4l2_subdev *sd, ++ struct media_link *link, ++ struct v4l2_subdev_format *source_fmt, ++ struct v4l2_subdev_format *sink_fmt) ++{ ++ struct pisp_fe_device *fe = to_pisp_fe_device(sd); ++ ++ pisp_fe_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index); ++ ++ /* The width, height and code must match. */ ++ if (source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.code != sink_fmt->format.code) { ++ pisp_fe_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", ++ __func__, ++ source_fmt->format.width, ++ source_fmt->format.height, ++ source_fmt->format.code, ++ sink_fmt->format.width, ++ sink_fmt->format.height, ++ sink_fmt->format.code); ++ return -EPIPE; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops pisp_fe_subdev_pad_ops = { ++ .init_cfg = pisp_fe_init_cfg, ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = pisp_fe_pad_set_fmt, ++ .link_validate = pisp_fe_link_validate, ++}; ++ ++static const struct media_entity_operations pisp_fe_entity_ops = { ++ .link_validate = v4l2_subdev_link_validate, ++}; ++ ++static const struct v4l2_subdev_ops pisp_fe_subdev_ops = { ++ .pad = &pisp_fe_subdev_pad_ops, ++}; ++ ++int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs) ++{ ++ int ret; ++ ++ debugfs_create_file("pisp_regs", 0444, debugfs, fe, &pisp_regs_fops); ++ ++ fe->hw_revision = pisp_fe_reg_read(fe, FE_VERSION); ++ pisp_fe_info("PiSP FE HW v%u.%u\n", ++ (fe->hw_revision >> 24) & 0xff, ++ (fe->hw_revision >> 20) & 0x0f); ++ ++ fe->pad[FE_STREAM_PAD].flags = ++ MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; ++ fe->pad[FE_CONFIG_PAD].flags = MEDIA_PAD_FL_SINK; ++ fe->pad[FE_OUTPUT0_PAD].flags = MEDIA_PAD_FL_SOURCE; ++ fe->pad[FE_OUTPUT1_PAD].flags = MEDIA_PAD_FL_SOURCE; ++ fe->pad[FE_STATS_PAD].flags = MEDIA_PAD_FL_SOURCE; ++ ++ ret = media_entity_pads_init(&fe->sd.entity, ARRAY_SIZE(fe->pad), ++ fe->pad); ++ if (ret) ++ return ret; ++ ++ /* Initialize subdev */ ++ v4l2_subdev_init(&fe->sd, &pisp_fe_subdev_ops); ++ fe->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; ++ fe->sd.entity.ops = &pisp_fe_entity_ops; ++ fe->sd.entity.name = "pisp-fe"; ++ fe->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ fe->sd.owner = THIS_MODULE; ++ snprintf(fe->sd.name, sizeof(fe->sd.name), "pisp-fe"); ++ ++ ret = v4l2_subdev_init_finalize(&fe->sd); ++ if (ret) ++ goto err_entity_cleanup; ++ ++ ret = v4l2_device_register_subdev(fe->v4l2_dev, &fe->sd); ++ if (ret) { ++ pisp_fe_err("Failed register pisp fe subdev (%d)\n", ret); ++ goto err_subdev_cleanup; ++ } ++ ++ /* Must be in IDLE state (STATUS == 0) here. */ ++ WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); ++ ++ return 0; ++ ++err_subdev_cleanup: ++ v4l2_subdev_cleanup(&fe->sd); ++err_entity_cleanup: ++ media_entity_cleanup(&fe->sd.entity); ++ ++ return ret; ++} ++ ++void pisp_fe_uninit(struct pisp_fe_device *fe) ++{ ++ v4l2_device_unregister_subdev(&fe->sd); ++ v4l2_subdev_cleanup(&fe->sd); ++ media_entity_cleanup(&fe->sd.entity); ++} +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.h +@@ -0,0 +1,53 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * PiSP Front End driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_H_ ++#define _PISP_FE_H_ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "pisp_fe_config.h" ++ ++enum pisp_fe_pads { ++ FE_STREAM_PAD, ++ FE_CONFIG_PAD, ++ FE_OUTPUT0_PAD, ++ FE_OUTPUT1_PAD, ++ FE_STATS_PAD, ++ FE_NUM_PADS ++}; ++ ++struct pisp_fe_device { ++ /* Parent V4l2 device */ ++ struct v4l2_device *v4l2_dev; ++ void __iomem *base; ++ u32 hw_revision; ++ ++ u16 inframe_count; ++ struct media_pad pad[FE_NUM_PADS]; ++ struct v4l2_subdev sd; ++}; ++ ++void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof); ++int pisp_fe_validate_config(struct pisp_fe_device *fe, ++ struct pisp_fe_config *cfg, ++ struct v4l2_format const *f0, ++ struct v4l2_format const *f1); ++void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs, ++ struct pisp_fe_config *cfg); ++void pisp_fe_start(struct pisp_fe_device *fe); ++void pisp_fe_stop(struct pisp_fe_device *fe); ++int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs); ++void pisp_fe_uninit(struct pisp_fe_device *fe); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h +@@ -0,0 +1,272 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP Front End Driver Configuration structures ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_CONFIG_ ++#define _PISP_FE_CONFIG_ ++ ++#include ++ ++#include "pisp_statistics.h" ++ ++#define PISP_FE_NUM_OUTPUTS 2 ++ ++enum pisp_fe_enable { ++ PISP_FE_ENABLE_INPUT = 0x000001, ++ PISP_FE_ENABLE_DECOMPRESS = 0x000002, ++ PISP_FE_ENABLE_DECOMPAND = 0x000004, ++ PISP_FE_ENABLE_BLA = 0x000008, ++ PISP_FE_ENABLE_DPC = 0x000010, ++ PISP_FE_ENABLE_STATS_CROP = 0x000020, ++ PISP_FE_ENABLE_DECIMATE = 0x000040, ++ PISP_FE_ENABLE_BLC = 0x000080, ++ PISP_FE_ENABLE_CDAF_STATS = 0x000100, ++ PISP_FE_ENABLE_AWB_STATS = 0x000200, ++ PISP_FE_ENABLE_RGBY = 0x000400, ++ PISP_FE_ENABLE_LSC = 0x000800, ++ PISP_FE_ENABLE_AGC_STATS = 0x001000, ++ PISP_FE_ENABLE_CROP0 = 0x010000, ++ PISP_FE_ENABLE_DOWNSCALE0 = 0x020000, ++ PISP_FE_ENABLE_COMPRESS0 = 0x040000, ++ PISP_FE_ENABLE_OUTPUT0 = 0x080000, ++ PISP_FE_ENABLE_CROP1 = 0x100000, ++ PISP_FE_ENABLE_DOWNSCALE1 = 0x200000, ++ PISP_FE_ENABLE_COMPRESS1 = 0x400000, ++ PISP_FE_ENABLE_OUTPUT1 = 0x800000 ++}; ++ ++#define PISP_FE_ENABLE_CROP(i) (PISP_FE_ENABLE_CROP0 << (4 * (i))) ++#define PISP_FE_ENABLE_DOWNSCALE(i) (PISP_FE_ENABLE_DOWNSCALE0 << (4 * (i))) ++#define PISP_FE_ENABLE_COMPRESS(i) (PISP_FE_ENABLE_COMPRESS0 << (4 * (i))) ++#define PISP_FE_ENABLE_OUTPUT(i) (PISP_FE_ENABLE_OUTPUT0 << (4 * (i))) ++ ++/* ++ * We use the enable flags to show when blocks are "dirty", but we need some ++ * extra ones too. ++ */ ++enum pisp_fe_dirty { ++ PISP_FE_DIRTY_GLOBAL = 0x0001, ++ PISP_FE_DIRTY_FLOATING = 0x0002, ++ PISP_FE_DIRTY_OUTPUT_AXI = 0x0004 ++}; ++ ++struct pisp_fe_global_config { ++ u32 enables; ++ u8 bayer_order; ++ u8 pad[3]; ++}; ++ ++struct pisp_fe_input_axi_config { ++ /* burst length minus one, in the range 0..15; OR'd with flags */ ++ u8 maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields */ ++ u8 cache_prot; ++ /* QoS (only 4 LS bits are used) */ ++ u16 qos; ++}; ++ ++struct pisp_fe_output_axi_config { ++ /* burst length minus one, in the range 0..15; OR'd with flags */ ++ u8 maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields */ ++ u8 cache_prot; ++ /* QoS (4 bitfields of 4 bits each for different panic levels) */ ++ u16 qos; ++ /* For Panic mode: Output FIFO panic threshold */ ++ u16 thresh; ++ /* For Panic mode: Output FIFO statistics throttle threshold */ ++ u16 throttle; ++}; ++ ++struct pisp_fe_input_config { ++ u8 streaming; ++ u8 pad[3]; ++ struct pisp_image_format_config format; ++ struct pisp_fe_input_axi_config axi; ++ /* Extra cycles delay before issuing each burst request */ ++ u8 holdoff; ++ u8 pad2[3]; ++}; ++ ++struct pisp_fe_output_config { ++ struct pisp_image_format_config format; ++ u16 ilines; ++ u8 pad[2]; ++}; ++ ++struct pisp_fe_input_buffer_config { ++ u32 addr_lo; ++ u32 addr_hi; ++ u16 frame_id; ++ u16 pad; ++}; ++ ++#define PISP_FE_DECOMPAND_LUT_SIZE 65 ++ ++struct pisp_fe_decompand_config { ++ u16 lut[PISP_FE_DECOMPAND_LUT_SIZE]; ++ u16 pad; ++}; ++ ++struct pisp_fe_dpc_config { ++ u8 coeff_level; ++ u8 coeff_range; ++ u8 coeff_range2; ++#define PISP_FE_DPC_FLAG_FOLDBACK 1 ++#define PISP_FE_DPC_FLAG_VFLAG 2 ++ u8 flags; ++}; ++ ++#define PISP_FE_LSC_LUT_SIZE 16 ++ ++struct pisp_fe_lsc_config { ++ u8 shift; ++ u8 pad0; ++ u16 scale; ++ u16 centre_x; ++ u16 centre_y; ++ u16 lut[PISP_FE_LSC_LUT_SIZE]; ++}; ++ ++struct pisp_fe_rgby_config { ++ u16 gain_r; ++ u16 gain_g; ++ u16 gain_b; ++ u8 maxflag; ++ u8 pad; ++}; ++ ++struct pisp_fe_agc_stats_config { ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++ /* each weight only 4 bits */ ++ u8 weights[PISP_AGC_STATS_NUM_ZONES / 2]; ++ u16 row_offset_x; ++ u16 row_offset_y; ++ u16 row_size_x; ++ u16 row_size_y; ++ u8 row_shift; ++ u8 float_shift; ++ u8 pad1[2]; ++}; ++ ++struct pisp_fe_awb_stats_config { ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++ u8 shift; ++ u8 pad[3]; ++ u16 r_lo; ++ u16 r_hi; ++ u16 g_lo; ++ u16 g_hi; ++ u16 b_lo; ++ u16 b_hi; ++}; ++ ++struct pisp_fe_floating_stats_region { ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++}; ++ ++struct pisp_fe_floating_stats_config { ++ struct pisp_fe_floating_stats_region ++ regions[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++#define PISP_FE_CDAF_NUM_WEIGHTS 8 ++ ++struct pisp_fe_cdaf_stats_config { ++ u16 noise_constant; ++ u16 noise_slope; ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++ u16 skip_x; ++ u16 skip_y; ++ u32 mode; ++}; ++ ++struct pisp_fe_stats_buffer_config { ++ u32 addr_lo; ++ u32 addr_hi; ++}; ++ ++struct pisp_fe_crop_config { ++ u16 offset_x; ++ u16 offset_y; ++ u16 width; ++ u16 height; ++}; ++ ++enum pisp_fe_downscale_flags { ++ DOWNSCALE_BAYER = ++ 1, /* downscale the four Bayer components independently... */ ++ DOWNSCALE_BIN = ++ 2 /* ...without trying to preserve their spatial relationship */ ++}; ++ ++struct pisp_fe_downscale_config { ++ u8 xin; ++ u8 xout; ++ u8 yin; ++ u8 yout; ++ u8 flags; /* enum pisp_fe_downscale_flags */ ++ u8 pad[3]; ++ u16 output_width; ++ u16 output_height; ++}; ++ ++struct pisp_fe_output_buffer_config { ++ u32 addr_lo; ++ u32 addr_hi; ++}; ++ ++/* Each of the two output channels/branches: */ ++struct pisp_fe_output_branch_config { ++ struct pisp_fe_crop_config crop; ++ struct pisp_fe_downscale_config downscale; ++ struct pisp_compress_config compress; ++ struct pisp_fe_output_config output; ++ u32 pad; ++}; ++ ++/* And finally one to rule them all: */ ++struct pisp_fe_config { ++ /* I/O configuration: */ ++ struct pisp_fe_stats_buffer_config stats_buffer; ++ struct pisp_fe_output_buffer_config output_buffer[PISP_FE_NUM_OUTPUTS]; ++ struct pisp_fe_input_buffer_config input_buffer; ++ /* processing configuration: */ ++ struct pisp_fe_global_config global; ++ struct pisp_fe_input_config input; ++ struct pisp_decompress_config decompress; ++ struct pisp_fe_decompand_config decompand; ++ struct pisp_bla_config bla; ++ struct pisp_fe_dpc_config dpc; ++ struct pisp_fe_crop_config stats_crop; ++ u32 spare1; /* placeholder for future decimate configuration */ ++ struct pisp_bla_config blc; ++ struct pisp_fe_rgby_config rgby; ++ struct pisp_fe_lsc_config lsc; ++ struct pisp_fe_agc_stats_config agc_stats; ++ struct pisp_fe_awb_stats_config awb_stats; ++ struct pisp_fe_cdaf_stats_config cdaf_stats; ++ struct pisp_fe_floating_stats_config floating_stats; ++ struct pisp_fe_output_axi_config output_axi; ++ struct pisp_fe_output_branch_config ch[PISP_FE_NUM_OUTPUTS]; ++ /* non-register fields: */ ++ u32 dirty_flags; /* these use pisp_fe_enable */ ++ u32 dirty_flags_extra; /* these use pisp_fe_dirty */ ++}; ++ ++#endif /* _PISP_FE_CONFIG_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h +@@ -0,0 +1,62 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP Front End statistics definitions ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_STATISTICS_H_ ++#define _PISP_FE_STATISTICS_H_ ++ ++#define PISP_FLOATING_STATS_NUM_ZONES 4 ++#define PISP_AGC_STATS_NUM_BINS 1024 ++#define PISP_AGC_STATS_SIZE 16 ++#define PISP_AGC_STATS_NUM_ZONES (PISP_AGC_STATS_SIZE * PISP_AGC_STATS_SIZE) ++#define PISP_AGC_STATS_NUM_ROW_SUMS 512 ++ ++struct pisp_agc_statistics_zone { ++ u64 Y_sum; ++ u32 counted; ++ u32 pad; ++}; ++ ++struct pisp_agc_statistics { ++ u32 row_sums[PISP_AGC_STATS_NUM_ROW_SUMS]; ++ /* ++ * 32-bits per bin means an image (just less than) 16384x16384 pixels ++ * in size can weight every pixel from 0 to 15. ++ */ ++ u32 histogram[PISP_AGC_STATS_NUM_BINS]; ++ struct pisp_agc_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++#define PISP_AWB_STATS_SIZE 32 ++#define PISP_AWB_STATS_NUM_ZONES (PISP_AWB_STATS_SIZE * PISP_AWB_STATS_SIZE) ++ ++struct pisp_awb_statistics_zone { ++ u32 R_sum; ++ u32 G_sum; ++ u32 B_sum; ++ u32 counted; ++}; ++ ++struct pisp_awb_statistics { ++ struct pisp_awb_statistics_zone zones[PISP_AWB_STATS_NUM_ZONES]; ++ struct pisp_awb_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++#define PISP_CDAF_STATS_SIZE 8 ++#define PISP_CDAF_STATS_NUM_FOMS (PISP_CDAF_STATS_SIZE * PISP_CDAF_STATS_SIZE) ++ ++struct pisp_cdaf_statistics { ++ u64 foms[PISP_CDAF_STATS_NUM_FOMS]; ++ u64 floating[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++struct pisp_statistics { ++ struct pisp_awb_statistics awb; ++ struct pisp_agc_statistics agc; ++ struct pisp_cdaf_statistics cdaf; ++}; ++ ++#endif /* _PISP_FE_STATISTICS_H_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h +@@ -0,0 +1,144 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP Front End image definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_TYPES_H_ ++#define _PISP_FE_TYPES_H_ ++ ++/* This definition must match the format description in the hardware exactly! */ ++struct pisp_image_format_config { ++ /* size in pixels */ ++ u16 width, height; ++ /* must match struct pisp_image_format below */ ++ u32 format; ++ s32 stride; ++ /* some planar image formats will need a second stride */ ++ s32 stride2; ++}; ++ ++static_assert(sizeof(struct pisp_image_format_config) == 16); ++ ++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 ++ ++#endif /* _PISP_FE_TYPES_H_ */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch b/target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch new file mode 100644 index 0000000000..7d81e03429 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch @@ -0,0 +1,38 @@ +From 2be65d1fd1f7d3cf6f59b58b53e285400f04a160 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 15 Feb 2023 09:46:35 +0000 +Subject: [PATCH] dt-bindings: net: cdns,macb: AXI tuning properties + +Add optional properties to tune the AXI interface - +cdns,aw2w-max-pipe, cdns,ar2r-max-pipe and cdns,use-aw2b-fill. + +Signed-off-by: Phil Elwell +--- + .../devicetree/bindings/net/cdns,macb.yaml | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/Documentation/devicetree/bindings/net/cdns,macb.yaml ++++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml +@@ -121,6 +121,22 @@ properties: + Node containing PHY children. If this node is not present, then PHYs will + be direct children. + ++ cdns,aw2w-max-pipe: ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ description: ++ Maximum number of outstanding AXI write requests ++ ++ cdns,ar2r-max-pipe: ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ description: ++ Maximum number of outstanding AXI read requests ++ ++ cdns,use-aw2b-fill: ++ type: boolean ++ description: ++ If set, the maximum number of outstanding write transactions operates ++ between the AW to B AXI channel, instead of the AW to W AXI channel. ++ + patternProperties: + "^ethernet-phy@[0-9a-f]$": + type: object diff --git a/target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch b/target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch new file mode 100644 index 0000000000..06d69c7c4c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch @@ -0,0 +1,29 @@ +From 9ef0615a5c5f93cb72af8df3a2dae6d23b106eb5 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 21 Feb 2023 21:26:16 +0000 +Subject: [PATCH] ASoC: dwc: list all supported sample sizes + +The hardware configuration determines the maximum-supported sample size +for each channel, but TCRx allows smaller sizes to be specified at run +time. Include the smaller supported sizes in the formats array. + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -448,9 +448,9 @@ static const u32 bus_widths[COMP_MAX_DAT + static const u32 formats[COMP_MAX_WORDSIZE] = { + SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_FMTBIT_S16_LE, +- SNDRV_PCM_FMTBIT_S24_LE, +- SNDRV_PCM_FMTBIT_S24_LE, +- SNDRV_PCM_FMTBIT_S32_LE, ++ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, ++ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, ++ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, + 0, + 0, + 0 diff --git a/target/linux/bcm27xx/patches-6.1/950-0892-ASoC-dwc-Support-set_bclk_ratio.patch b/target/linux/bcm27xx/patches-6.1/950-0892-ASoC-dwc-Support-set_bclk_ratio.patch new file mode 100644 index 0000000000..b18e5f888f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0892-ASoC-dwc-Support-set_bclk_ratio.patch @@ -0,0 +1,59 @@ +From 06f794e8cb227249e03893e4b4923ff58556eb60 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 4 Mar 2021 14:49:23 +0000 +Subject: [PATCH] ASoC: dwc: Support set_bclk_ratio + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -351,11 +351,46 @@ static int dw_i2s_set_fmt(struct snd_soc + return ret; + } + ++static int dw_i2s_set_bclk_ratio(struct snd_soc_dai *cpu_dai, ++ unsigned int ratio) ++{ ++ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); ++ struct i2s_clk_config_data *config = &dev->config; ++ ++ dev_err(dev->dev, "%s(%d)\n", __func__, ratio); ++ switch (ratio) { ++ case 32: ++ config->data_width = 16; ++ dev->ccr = 0x00; ++ dev->xfer_resolution = 0x02; ++ break; ++ ++ case 48: ++ config->data_width = 24; ++ dev->ccr = 0x08; ++ dev->xfer_resolution = 0x04; ++ break; ++ ++ case 64: ++ config->data_width = 32; ++ dev->ccr = 0x10; ++ dev->xfer_resolution = 0x05; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ i2s_write_reg(dev->i2s_base, CCR, dev->ccr); ++ ++ return 0; ++} ++ + static const struct snd_soc_dai_ops dw_i2s_dai_ops = { + .hw_params = dw_i2s_hw_params, + .prepare = dw_i2s_prepare, + .trigger = dw_i2s_trigger, + .set_fmt = dw_i2s_set_fmt, ++ .set_bclk_ratio = dw_i2s_set_bclk_ratio, + }; + + #ifdef CONFIG_PM diff --git a/target/linux/bcm27xx/patches-6.1/950-0893-ASoC-dwc-Add-DMACR-handling.patch b/target/linux/bcm27xx/patches-6.1/950-0893-ASoC-dwc-Add-DMACR-handling.patch new file mode 100644 index 0000000000..474903c327 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0893-ASoC-dwc-Add-DMACR-handling.patch @@ -0,0 +1,81 @@ +From b3b1177092d4d2ba6df74042d39aa42c5055f687 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 3 Jul 2023 09:08:16 +0100 +Subject: [PATCH] ASoC: dwc: Add DMACR handling + +Add control of the DMACR register, which is required for paced DMA +(i.e. DREQ) support. + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 13 ++++++++++--- + sound/soc/dwc/local.h | 13 +++++++++++++ + 2 files changed, 23 insertions(+), 3 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -185,9 +185,9 @@ static void i2s_stop(struct dw_i2s_dev * + + static void dw_i2s_config(struct dw_i2s_dev *dev, int stream) + { +- u32 ch_reg; + struct i2s_clk_config_data *config = &dev->config; +- ++ u32 ch_reg; ++ u32 dmacr = 0; + + i2s_disable_channels(dev, stream); + +@@ -198,15 +198,22 @@ static void dw_i2s_config(struct dw_i2s_ + i2s_write_reg(dev->i2s_base, TFCR(ch_reg), + dev->fifo_th - 1); + i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); ++ dmacr |= (DMACR_DMAEN_TXCH0 << ch_reg); + } else { + i2s_write_reg(dev->i2s_base, RCR(ch_reg), + dev->xfer_resolution); + i2s_write_reg(dev->i2s_base, RFCR(ch_reg), + dev->fifo_th - 1); + i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); ++ dmacr |= (DMACR_DMAEN_RXCH0 << ch_reg); + } +- + } ++ if (stream == SNDRV_PCM_STREAM_PLAYBACK) ++ dmacr |= DMACR_DMAEN_TX; ++ else if (stream == SNDRV_PCM_STREAM_CAPTURE) ++ dmacr |= DMACR_DMAEN_RX; ++ ++ i2s_write_reg(dev->i2s_base, DMACR, dmacr); + } + + static int dw_i2s_hw_params(struct snd_pcm_substream *substream, +--- a/sound/soc/dwc/local.h ++++ b/sound/soc/dwc/local.h +@@ -25,6 +25,8 @@ + #define RXFFR 0x014 + #define TXFFR 0x018 + ++#define DMACR 0x200 ++ + /* Interrupt status register fields */ + #define ISR_TXFO BIT(5) + #define ISR_TXFE BIT(4) +@@ -47,6 +49,17 @@ + #define RFF(x) (0x40 * x + 0x050) + #define TFF(x) (0x40 * x + 0x054) + ++#define DMACR_DMAEN_TX BIT(17) ++#define DMACR_DMAEN_RX BIT(16) ++#define DMACR_DMAEN_TXCH3 BIT(11) ++#define DMACR_DMAEN_TXCH2 BIT(10) ++#define DMACR_DMAEN_TXCH1 BIT(9) ++#define DMACR_DMAEN_TXCH0 BIT(8) ++#define DMACR_DMAEN_RXCH3 BIT(3) ++#define DMACR_DMAEN_RXCH2 BIT(2) ++#define DMACR_DMAEN_RXCH1 BIT(1) ++#define DMACR_DMAEN_RXCH0 BIT(0) ++ + /* I2SCOMPRegisters */ + #define I2S_COMP_PARAM_2 0x01F0 + #define I2S_COMP_PARAM_1 0x01F4 diff --git a/target/linux/bcm27xx/patches-6.1/950-0894-ASOC-dwc-Improve-DMA-shutdown.patch b/target/linux/bcm27xx/patches-6.1/950-0894-ASOC-dwc-Improve-DMA-shutdown.patch new file mode 100644 index 0000000000..73704a8be3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0894-ASOC-dwc-Improve-DMA-shutdown.patch @@ -0,0 +1,128 @@ +From e6baee4502c0228c79408b047096a1259a84353f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 3 Jul 2023 10:14:43 +0100 +Subject: [PATCH] ASOC: dwc: Improve DMA shutdown + +Disabling the I2S interface with outstanding transfers prevents the +DMAC from shutting down, so keep it partially active after a stop. + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 72 ++++++++++++++++++++++++++++++++++++----- + 1 file changed, 64 insertions(+), 8 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -165,24 +165,26 @@ static void i2s_start(struct dw_i2s_dev + i2s_write_reg(dev->i2s_base, CER, 1); + } + +-static void i2s_stop(struct dw_i2s_dev *dev, +- struct snd_pcm_substream *substream) ++static void i2s_pause(struct dw_i2s_dev *dev, struct snd_pcm_substream *substream) + { + + i2s_clear_irqs(dev, substream->stream); +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- i2s_write_reg(dev->i2s_base, ITER, 0); +- else +- i2s_write_reg(dev->i2s_base, IRER, 0); + + i2s_disable_irqs(dev, substream->stream, 8); + + if (!dev->active) { + i2s_write_reg(dev->i2s_base, CER, 0); +- i2s_write_reg(dev->i2s_base, IER, 0); ++ /* Keep the device enabled until the shutdown - do not clear IER */ + } + } + ++static void i2s_stop(struct dw_i2s_dev *dev, struct snd_pcm_substream *substream) ++{ ++ i2s_clear_irqs(dev, substream->stream); ++ ++ i2s_disable_irqs(dev, substream->stream, 8); ++} ++ + static void dw_i2s_config(struct dw_i2s_dev *dev, int stream) + { + struct i2s_clk_config_data *config = &dev->config; +@@ -288,6 +290,55 @@ static int dw_i2s_hw_params(struct snd_p + return 0; + } + ++static int dw_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *cpu_dai) ++{ ++ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); ++ union dw_i2s_snd_dma_data *dma_data = NULL; ++ u32 dmacr; ++ ++ dev_dbg(dev->dev, "%s(%s)\n", __func__, substream->name); ++ if (!(dev->capability & DWC_I2S_RECORD) && ++ substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ return -EINVAL; ++ ++ if (!(dev->capability & DWC_I2S_PLAY) && ++ substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ return -EINVAL; ++ ++ dw_i2s_config(dev, substream->stream); ++ dmacr = i2s_read_reg(dev->i2s_base, DMACR); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ dma_data = &dev->play_dma_data; ++ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ dma_data = &dev->capture_dma_data; ++ ++ snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); ++ i2s_write_reg(dev->i2s_base, DMACR, dmacr); ++ ++ return 0; ++} ++ ++static void dw_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ dev_dbg(dev->dev, "%s(%s)\n", __func__, substream->name); ++ i2s_disable_channels(dev, substream->stream); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ i2s_write_reg(dev->i2s_base, ITER, 0); ++ else ++ i2s_write_reg(dev->i2s_base, IRER, 0); ++ ++ i2s_disable_irqs(dev, substream->stream, 8); ++ ++ if (!dev->active) { ++ i2s_write_reg(dev->i2s_base, CER, 0); ++ i2s_write_reg(dev->i2s_base, IER, 0); ++ } ++} ++ + static int dw_i2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { +@@ -315,9 +366,12 @@ static int dw_i2s_trigger(struct snd_pcm + i2s_start(dev, substream); + break; + ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ dev->active--; ++ i2s_pause(dev, substream); ++ break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: +- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dev->active--; + i2s_stop(dev, substream); + break; +@@ -394,6 +448,8 @@ static int dw_i2s_set_bclk_ratio(struct + + static const struct snd_soc_dai_ops dw_i2s_dai_ops = { + .hw_params = dw_i2s_hw_params, ++ .startup = dw_i2s_startup, ++ .shutdown = dw_i2s_shutdown, + .prepare = dw_i2s_prepare, + .trigger = dw_i2s_trigger, + .set_fmt = dw_i2s_set_fmt, diff --git a/target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch b/target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch new file mode 100644 index 0000000000..fa5eb61044 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch @@ -0,0 +1,88 @@ +From 9c6694c24f26ea435165431d41c72451fadbd753 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 21 Jul 2023 12:07:16 +0100 +Subject: [PATCH] ASOC: dwc: Fix 16-bit audio handling + +IMO the Synopsys datasheet could be clearer in this area, but it seems +that the DMA data ports (DMATX and DMARX) expect left and right samples +in alternate writes; if a stereo pair is pushed in a single 32-bit +write, the upper half is ignored, leading to double speed audio with a +confused stereo image. Make sure the necessary changes happen by +updating the DMA configuration data in the hw_params method. + +The set_bclk_ratio change was made at a time when it looked like it +could be causing an error, but I think the division of responsibilities +is clearer this way (and the kernel log clearer without the info-level +message). + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -223,23 +223,34 @@ static int dw_i2s_hw_params(struct snd_p + { + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); + struct i2s_clk_config_data *config = &dev->config; ++ union dw_i2s_snd_dma_data *dma_data = NULL; + int ret; + ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ dma_data = &dev->play_dma_data; ++ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ dma_data = &dev->capture_dma_data; ++ else ++ return -1; ++ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + config->data_width = 16; ++ dma_data->dt.addr_width = 2; + dev->ccr = 0x00; + dev->xfer_resolution = 0x02; + break; + + case SNDRV_PCM_FORMAT_S24_LE: + config->data_width = 24; ++ dma_data->dt.addr_width = 4; + dev->ccr = 0x08; + dev->xfer_resolution = 0x04; + break; + + case SNDRV_PCM_FORMAT_S32_LE: + config->data_width = 32; ++ dma_data->dt.addr_width = 4; + dev->ccr = 0x10; + dev->xfer_resolution = 0x05; + break; +@@ -418,24 +429,21 @@ static int dw_i2s_set_bclk_ratio(struct + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); + struct i2s_clk_config_data *config = &dev->config; + +- dev_err(dev->dev, "%s(%d)\n", __func__, ratio); ++ dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio); ++ if (ratio < config->data_width * 2) ++ return -EINVAL; ++ + switch (ratio) { + case 32: +- config->data_width = 16; + dev->ccr = 0x00; +- dev->xfer_resolution = 0x02; + break; + + case 48: +- config->data_width = 24; + dev->ccr = 0x08; +- dev->xfer_resolution = 0x04; + break; + + case 64: +- config->data_width = 32; + dev->ccr = 0x10; +- dev->xfer_resolution = 0x05; + break; + default: + return -EINVAL; diff --git a/target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch b/target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch new file mode 100644 index 0000000000..9f4f7a0c9a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch @@ -0,0 +1,304 @@ +From f476db1b71e8b82e5299168f963a2fefb7a395e2 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 1 Sep 2023 14:07:48 +0100 +Subject: [PATCH] ASoC: bcm: Remove dependency on BCM2835 I2S + +These soundcard drivers don't rely on a specific I2S interface, so +remove the dependency declarations. + +See: https://github.com/raspberrypi/linux-2712/issues/111 + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/Kconfig | 40 +--------------------------------------- + 1 file changed, 1 insertion(+), 39 deletions(-) + +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -29,13 +29,11 @@ config SND_BCM63XX_I2S_WHISTLER + + config SND_BCM2708_SOC_CHIPDIP_DAC + tristate "Support for the ChipDip DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + help + Say Y or M if you want to add support for the ChipDip DAC soundcard + + config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD + tristate "Support for Google voiceHAT soundcard" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_VOICEHAT + select SND_RPI_SIMPLE_SOUNDCARD + help +@@ -43,7 +41,6 @@ config SND_BCM2708_SOC_GOOGLEVOICEHAT_SO + + config SND_BCM2708_SOC_HIFIBERRY_DAC + tristate "Support for HifiBerry DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM5102A + select SND_RPI_SIMPLE_SOUNDCARD + help +@@ -51,7 +48,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + + config SND_BCM2708_SOC_HIFIBERRY_DACPLUS + tristate "Support for HifiBerry DAC+" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x + select SND_SOC_TPA6130A2 + select COMMON_CLK_HIFIBERRY_DACPRO +@@ -60,7 +56,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS + + config SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD + tristate "Support for HifiBerry DAC+ HD" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM179X_I2C + select COMMON_CLK_HIFIBERRY_DACPLUSHD + help +@@ -68,7 +63,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS + + config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC + tristate "Support for HifiBerry DAC+ADC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x_I2C + select SND_SOC_DMIC + select COMMON_CLK_HIFIBERRY_DACPRO +@@ -77,7 +71,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS + + config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO + tristate "Support for HifiBerry DAC+ADC PRO" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x_I2C + select SND_SOC_PCM186X_I2C + select SND_SOC_TPA6130A2 +@@ -87,29 +80,25 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS + + config SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP + tristate "Support for HifiBerry DAC+DSP" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_RPI_SIMPLE_SOUNDCARD + help + Say Y or M if you want to add support for HifiBerry DSP-DAC. + + config SND_BCM2708_SOC_HIFIBERRY_DIGI + tristate "Support for HifiBerry Digi" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8804 + help + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. + + config SND_BCM2708_SOC_HIFIBERRY_AMP + tristate "Support for the HifiBerry Amp" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_TAS5713 + select SND_RPI_SIMPLE_SOUNDCARD + help + Say Y or M if you want to add support for the HifiBerry Amp amplifier board. + +- config SND_BCM2708_SOC_PIFI_40 ++config SND_BCM2708_SOC_PIFI_40 + tristate "Support for the PiFi-40 amp" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_TAS571X + select SND_PIFI_40 + help +@@ -117,7 +106,6 @@ config SND_BCM2708_SOC_HIFIBERRY_AMP + + config SND_BCM2708_SOC_RPI_CIRRUS + tristate "Support for Cirrus Logic Audio Card" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM5102 + select SND_SOC_WM8804 + help +@@ -126,7 +114,6 @@ config SND_BCM2708_SOC_RPI_CIRRUS + + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM1794A + select SND_RPI_SIMPLE_SOUNDCARD + help +@@ -134,14 +121,12 @@ config SND_BCM2708_SOC_RPI_DAC + + config SND_BCM2708_SOC_RPI_PROTO + tristate "Support for Rpi-PROTO" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8731_I2C + help + Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). + + config SND_BCM2708_SOC_JUSTBOOM_BOTH + tristate "Support for simultaneous JustBoom Digi and JustBoom DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8804 + select SND_SOC_PCM512x + help +@@ -153,14 +138,12 @@ config SND_BCM2708_SOC_JUSTBOOM_BOTH + + config SND_BCM2708_SOC_JUSTBOOM_DAC + tristate "Support for JustBoom DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x + help + Say Y or M if you want to add support for JustBoom DAC. + + config SND_BCM2708_SOC_JUSTBOOM_DIGI + tristate "Support for JustBoom Digi" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8804 + select SND_RPI_WM8804_SOUNDCARD + help +@@ -168,21 +151,18 @@ config SND_BCM2708_SOC_JUSTBOOM_DIGI + + config SND_BCM2708_SOC_IQAUDIO_CODEC + tristate "Support for IQaudIO-CODEC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_DA7213 + help + Say Y or M if you want to add support for IQaudIO-CODEC. + + config SND_BCM2708_SOC_IQAUDIO_DAC + tristate "Support for IQaudIO-DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x_I2C + help + Say Y or M if you want to add support for IQaudIO-DAC. + + config SND_BCM2708_SOC_IQAUDIO_DIGI + tristate "Support for IQAudIO Digi" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8804 + select SND_RPI_WM8804_SOUNDCARD + help +@@ -190,14 +170,12 @@ config SND_BCM2708_SOC_IQAUDIO_DIGI + + config SND_BCM2708_SOC_I_SABRE_Q2M + tristate "Support for Audiophonics I-Sabre Q2M DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_I_SABRE_CODEC + help + Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC + + config SND_BCM2708_SOC_ADAU1977_ADC + tristate "Support for ADAU1977 ADC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_ADAU1977_I2C + select SND_RPI_SIMPLE_SOUNDCARD + help +@@ -205,35 +183,30 @@ config SND_BCM2708_SOC_ADAU1977_ADC + + config SND_AUDIOINJECTOR_PI_SOUNDCARD + tristate "Support for audioinjector.net Pi add on soundcard" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8731_I2C + help + Say Y or M if you want to add support for audioinjector.net Pi Hat + + config SND_AUDIOINJECTOR_OCTO_SOUNDCARD + tristate "Support for audioinjector.net Octo channel (Hat) soundcard" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_CS42XX8_I2C + help + Say Y or M if you want to add support for audioinjector.net octo add on + + config SND_AUDIOINJECTOR_ISOLATED_SOUNDCARD + tristate "Support for audioinjector.net isolated DAC and ADC soundcard" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_CS4271_I2C + help + Say Y or M if you want to add support for audioinjector.net isolated soundcard + + config SND_AUDIOSENSE_PI + tristate "Support for AudioSense Add-On Soundcard" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_TLV320AIC32X4_I2C + help + Say Y or M if you want to add support for tlv320aic32x4 add-on + + config SND_DIGIDAC1_SOUNDCARD + tristate "Support for Red Rocks Audio DigiDAC1" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8804 + select SND_SOC_WM8741 + help +@@ -241,35 +214,30 @@ config SND_DIGIDAC1_SOUNDCARD + + config SND_BCM2708_SOC_DIONAUDIO_LOCO + tristate "Support for Dion Audio LOCO DAC-AMP" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM5102a + help + Say Y or M if you want to add support for Dion Audio LOCO. + + config SND_BCM2708_SOC_DIONAUDIO_LOCO_V2 + tristate "Support for Dion Audio LOCO-V2 DAC-AMP" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM5122 + help + Say Y or M if you want to add support for Dion Audio LOCO-V2. + + config SND_BCM2708_SOC_ALLO_PIANO_DAC + tristate "Support for Allo Piano DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x_I2C + help + Say Y or M if you want to add support for Allo Piano DAC. + + config SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS + tristate "Support for Allo Piano DAC Plus" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x_I2C + help + Say Y or M if you want to add support for Allo Piano DAC Plus. + + config SND_BCM2708_SOC_ALLO_BOSS_DAC + tristate "Support for Allo Boss DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_PCM512x_I2C + select COMMON_CLK_HIFIBERRY_DACPRO + help +@@ -277,7 +245,6 @@ config SND_BCM2708_SOC_ALLO_BOSS_DAC + + config SND_BCM2708_SOC_ALLO_BOSS2_DAC + tristate "Support for Allo Boss2 DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + depends on I2C + select REGMAP_I2C + select SND_AUDIO_GRAPH_CARD +@@ -286,7 +253,6 @@ config SND_BCM2708_SOC_ALLO_BOSS2_DAC + + config SND_BCM2708_SOC_ALLO_DIGIONE + tristate "Support for Allo DigiOne" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_WM8804 + select SND_RPI_WM8804_SOUNDCARD + help +@@ -294,7 +260,6 @@ config SND_BCM2708_SOC_ALLO_DIGIONE + + config SND_BCM2708_SOC_ALLO_KATANA_DAC + tristate "Support for Allo Katana DAC" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + depends on I2C + select REGMAP_I2C + select SND_AUDIO_GRAPH_CARD +@@ -303,14 +268,12 @@ config SND_BCM2708_SOC_ALLO_KATANA_DAC + + config SND_BCM2708_SOC_FE_PI_AUDIO + tristate "Support for Fe-Pi-Audio" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_SGTL5000 + help + Say Y or M if you want to add support for Fe-Pi-Audio. + + config SND_PISOUND + tristate "Support for Blokas Labs pisound" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_RAWMIDI + help + Say Y or M if you want to add support for Blokas Labs pisound. +@@ -328,7 +291,6 @@ config SND_RPI_WM8804_SOUNDCARD + + config SND_DACBERRY400 + tristate "Support for DACBERRY400 Soundcard" +- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_TLV320AIC3X_I2C + help + Say Y or M if you want to add support for tlv320aic3x add-on diff --git a/target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch new file mode 100644 index 0000000000..c3cf21455b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch @@ -0,0 +1,343 @@ +From cad3c92ff0c1a5fa539d08b695b0f6b326924890 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Mar 2023 18:04:42 +0000 +Subject: [PATCH] hwmon: Add RP1 ADC and temperature driver + +Signed-off-by: Phil Elwell +--- + drivers/hwmon/Kconfig | 7 + + drivers/hwmon/Makefile | 1 + + drivers/hwmon/rp1-adc.c | 301 ++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 309 insertions(+) + create mode 100644 drivers/hwmon/rp1-adc.c + +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -2331,6 +2331,13 @@ config SENSORS_INTEL_M10_BMC_HWMON + sensors monitor various telemetry data of different components on the + card, e.g. board temperature, FPGA core temperature/voltage/current. + ++config SENSORS_RP1_ADC ++ tristate "RP1 ADC and temperature sensor driver" ++ depends on MFD_RP1 ++ help ++ Say yes here to enable support for the voltage and temperature ++ sensors of the Raspberry Pi RP1 peripheral chip. ++ + if ACPI + + comment "ACPI drivers" +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -173,6 +173,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591 + obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o + obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o + obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o ++obj-$(CONFIG_SENSORS_RP1_ADC) += rp1-adc.o + obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o + obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o + obj-$(CONFIG_SENSORS_SBRMI) += sbrmi.o +--- /dev/null ++++ b/drivers/hwmon/rp1-adc.c +@@ -0,0 +1,301 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for the RP1 ADC and temperature sensor ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "rp1-adc" ++ ++#define RP1_ADC_CS 0x00 ++#define RP1_ADC_RESULT 0x04 ++#define RP1_ADC_FCS 0x08 ++#define RP1_ADC_FIFO 0x0c ++#define RP1_ADC_DIV 0x10 ++ ++#define RP1_ADC_INTR 0x14 ++#define RP1_ADC_INTE 0x18 ++#define RP1_ADC_INTF 0x1c ++#define RP1_ADC_INTS 0x20 ++ ++#define RP1_ADC_RWTYPE_SET 0x2000 ++#define RP1_ADC_RWTYPE_CLR 0x3000 ++ ++#define RP1_ADC_CS_RROBIN_MASK 0x1f ++#define RP1_ADC_CS_RROBIN_SHIFT 16 ++#define RP1_ADC_CS_AINSEL_MASK 0x7 ++#define RP1_ADC_CS_AINSEL_SHIFT 12 ++#define RP1_ADC_CS_ERR_STICKY 0x400 ++#define RP1_ADC_CS_ERR 0x200 ++#define RP1_ADC_CS_READY 0x100 ++#define RP1_ADC_CS_START_MANY 0x8 ++#define RP1_ADC_CS_START_ONCE 0x4 ++#define RP1_ADC_CS_TS_EN 0x2 ++#define RP1_ADC_CS_EN 0x1 ++ ++#define RP1_ADC_FCS_THRESH_MASK 0xf ++#define RP1_ADC_FCS_THRESH_SHIFT 24 ++#define RP1_ADC_FCS_LEVEL_MASK 0xf ++#define RP1_ADC_FCS_LEVEL_SHIFT 16 ++#define RP1_ADC_FCS_OVER 0x800 ++#define RP1_ADC_FCS_UNDER 0x400 ++#define RP1_ADC_FCS_FULL 0x200 ++#define RP1_ADC_FCS_EMPTY 0x100 ++#define RP1_ADC_FCS_DREQ_EN 0x8 ++#define RP1_ADC_FCS_ERR 0x4 ++#define RP1_ADC_FCS_SHIFR 0x2 ++#define RP1_ADC_FCS_EN 0x1 ++ ++#define RP1_ADC_FIFO_ERR 0x8000 ++#define RP1_ADC_FIFO_VAL_MASK 0xfff ++ ++#define RP1_ADC_DIV_INT_MASK 0xffff ++#define RP1_ADC_DIV_INT_SHIFT 8 ++#define RP1_ADC_DIV_FRAC_MASK 0xff ++#define RP1_ADC_DIV_FRAC_SHIFT 0 ++ ++struct rp1_adc_data { ++ void __iomem *base; ++ spinlock_t lock; ++ struct device *hwmon_dev; ++ int vref_mv; ++}; ++ ++static int rp1_adc_ready_wait(struct rp1_adc_data *data) ++{ ++ int retries = 10; ++ ++ while (retries && !(readl(data->base + RP1_ADC_CS) & RP1_ADC_CS_READY)) ++ retries--; ++ ++ return retries ? 0 : -EIO; ++} ++ ++static int rp1_adc_read(struct rp1_adc_data *data, ++ struct device_attribute *devattr, unsigned int *val) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ int channel = attr->index; ++ int ret; ++ ++ spin_lock(&data->lock); ++ ++ writel(RP1_ADC_CS_AINSEL_MASK << RP1_ADC_CS_AINSEL_SHIFT, ++ data->base + RP1_ADC_RWTYPE_CLR + RP1_ADC_CS); ++ writel(channel << RP1_ADC_CS_AINSEL_SHIFT, ++ data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS); ++ writel(RP1_ADC_CS_START_ONCE, ++ data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS); ++ ++ ret = rp1_adc_ready_wait(data); ++ if (!ret) ++ *val = readl(data->base + RP1_ADC_RESULT); ++ ++ spin_unlock(&data->lock); ++ ++ return ret; ++} ++ ++static int rp1_adc_to_mv(struct rp1_adc_data *data, unsigned int val) ++{ ++ return ((u64)data->vref_mv * val) / 0xfff; ++} ++ ++static ssize_t rp1_adc_show(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct rp1_adc_data *data = dev_get_drvdata(dev); ++ unsigned int val; ++ int ret; ++ ++ ret = rp1_adc_read(data, devattr, &val); ++ if (ret) ++ return ret; ++ ++ return sprintf(buf, "%d\n", rp1_adc_to_mv(data, val)); ++} ++ ++static ssize_t rp1_adc_temp_show(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct rp1_adc_data *data = dev_get_drvdata(dev); ++ unsigned int val; ++ int ret, mv, mc; ++ ++ writel(RP1_ADC_CS_TS_EN, ++ data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS); ++ ret = rp1_adc_read(data, devattr, &val); ++ if (ret) ++ return ret; ++ ++ mv = rp1_adc_to_mv(data, val); ++ ++ /* T = 27 - (ADC_voltage - 0.706)/0.001721 */ ++ ++ mc = 27000 - DIV_ROUND_CLOSEST((mv - 706) * (s64)1000000, 1721); ++ ++ return sprintf(buf, "%d\n", mc); ++} ++ ++static ssize_t rp1_adc_raw_show(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct rp1_adc_data *data = dev_get_drvdata(dev); ++ unsigned int val; ++ int ret = rp1_adc_read(data, devattr, &val); ++ ++ if (ret) ++ return ret; ++ ++ return sprintf(buf, "%u\n", val); ++} ++ ++static ssize_t rp1_adc_temp_raw_show(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct rp1_adc_data *data = dev_get_drvdata(dev); ++ unsigned int val; ++ int ret = rp1_adc_read(data, devattr, &val); ++ ++ if (ret) ++ return ret; ++ ++ return sprintf(buf, "%u\n", val); ++} ++ ++static SENSOR_DEVICE_ATTR_RO(in1_input, rp1_adc, 0); ++static SENSOR_DEVICE_ATTR_RO(in2_input, rp1_adc, 1); ++static SENSOR_DEVICE_ATTR_RO(in3_input, rp1_adc, 2); ++static SENSOR_DEVICE_ATTR_RO(in4_input, rp1_adc, 3); ++static SENSOR_DEVICE_ATTR_RO(temp1_input, rp1_adc_temp, 4); ++static SENSOR_DEVICE_ATTR_RO(in1_raw, rp1_adc_raw, 0); ++static SENSOR_DEVICE_ATTR_RO(in2_raw, rp1_adc_raw, 1); ++static SENSOR_DEVICE_ATTR_RO(in3_raw, rp1_adc_raw, 2); ++static SENSOR_DEVICE_ATTR_RO(in4_raw, rp1_adc_raw, 3); ++static SENSOR_DEVICE_ATTR_RO(temp1_raw, rp1_adc_temp_raw, 4); ++ ++static struct attribute *rp1_adc_attrs[] = { ++ &sensor_dev_attr_in1_input.dev_attr.attr, ++ &sensor_dev_attr_in2_input.dev_attr.attr, ++ &sensor_dev_attr_in3_input.dev_attr.attr, ++ &sensor_dev_attr_in4_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_in1_raw.dev_attr.attr, ++ &sensor_dev_attr_in2_raw.dev_attr.attr, ++ &sensor_dev_attr_in3_raw.dev_attr.attr, ++ &sensor_dev_attr_in4_raw.dev_attr.attr, ++ &sensor_dev_attr_temp1_raw.dev_attr.attr, ++ NULL ++}; ++ ++static umode_t rp1_adc_is_visible(struct kobject *kobj, ++ struct attribute *attr, int index) ++{ ++ return 0444; ++} ++ ++static const struct attribute_group rp1_adc_group = { ++ .attrs = rp1_adc_attrs, ++ .is_visible = rp1_adc_is_visible, ++}; ++__ATTRIBUTE_GROUPS(rp1_adc); ++ ++static int __init rp1_adc_probe(struct platform_device *pdev) ++{ ++ struct rp1_adc_data *data; ++ struct regulator *reg; ++ struct clk *clk; ++ int vref_uv, ret; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ spin_lock_init(&data->lock); ++ ++ data->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(data->base)) ++ return PTR_ERR(data->base); ++ ++ platform_set_drvdata(pdev, data); ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) ++ return -ENODEV; ++ ++ clk_set_rate(clk, 50000000); ++ clk_prepare_enable(clk); ++ ++ reg = devm_regulator_get(&pdev->dev, "vref"); ++ if (IS_ERR(reg)) ++ return PTR_ERR(reg); ++ ++ vref_uv = regulator_get_voltage(reg); ++ data->vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000); ++ ++ data->hwmon_dev = ++ devm_hwmon_device_register_with_groups(&pdev->dev, ++ "rp1_adc", ++ data, ++ rp1_adc_groups); ++ if (IS_ERR(data->hwmon_dev)) { ++ ret = PTR_ERR(data->hwmon_dev); ++ dev_err(&pdev->dev, "hwmon_device_register failed with %d.\n", ret); ++ goto err_register; ++ } ++ ++ /* Disable interrupts */ ++ writel(0, data->base + RP1_ADC_INTE); ++ ++ /* Enable the block, clearing any sticky error */ ++ writel(RP1_ADC_CS_EN | RP1_ADC_CS_ERR_STICKY, data->base + RP1_ADC_CS); ++ ++ return 0; ++ ++err_register: ++ sysfs_remove_group(&pdev->dev.kobj, &rp1_adc_group); ++ ++ return ret; ++} ++ ++static int rp1_adc_remove(struct platform_device *pdev) ++{ ++ struct rp1_adc_data *data = platform_get_drvdata(pdev); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id rp1_adc_dt_ids[] = { ++ { .compatible = "raspberrypi,rp1-adc", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, rp1_adc_dt_ids); ++ ++static struct platform_driver rp1_adc_driver = { ++ .remove = rp1_adc_remove, ++ .driver = { ++ .name = MODULE_NAME, ++ .of_match_table = rp1_adc_dt_ids, ++ }, ++}; ++ ++module_platform_driver_probe(rp1_adc_driver, rp1_adc_probe); ++ ++MODULE_DESCRIPTION("RP1 ADC driver"); ++MODULE_AUTHOR("Phil Elwell "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch new file mode 100644 index 0000000000..37210173db --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch @@ -0,0 +1,69 @@ +From 0c7aeb96fd3ab68011ba6c24239c501190890308 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 8 Mar 2023 14:27:58 +0000 +Subject: [PATCH] mfd: bcm2835-pm: Add support for BCM2712 + +BCM2712 lacks the "asb" and "rpivid_asb" register ranges, but still +requires the use of the bcm2835-power driver to reset the V3D block. + +Signed-off-by: Phil Elwell +--- + drivers/mfd/bcm2835-pm.c | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +--- a/drivers/mfd/bcm2835-pm.c ++++ b/drivers/mfd/bcm2835-pm.c +@@ -69,12 +69,30 @@ static int bcm2835_pm_get_pdata(struct p + return 0; + } + ++static const struct of_device_id bcm2835_pm_of_match[] = { ++ { .compatible = "brcm,bcm2835-pm-wdt", }, ++ { .compatible = "brcm,bcm2835-pm", }, ++ { .compatible = "brcm,bcm2711-pm", }, ++ { .compatible = "brcm,bcm2712-pm", .data = (const void *)1}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match); ++ + static int bcm2835_pm_probe(struct platform_device *pdev) + { ++ const struct of_device_id *of_id; + struct device *dev = &pdev->dev; + struct bcm2835_pm *pm; ++ bool is_2712; + int ret; + ++ of_id = of_match_node(bcm2835_pm_of_match, pdev->dev.of_node); ++ if (!of_id) { ++ dev_err(&pdev->dev, "Failed to match compatible string\n"); ++ return -EINVAL; ++ } ++ is_2712 = !!of_id->data; ++ + pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL); + if (!pm) + return -ENOMEM; +@@ -97,21 +115,13 @@ static int bcm2835_pm_probe(struct platf + * bcm2835-pm binding as the key for whether we can reference + * the full PM register range and support power domains. + */ +- if (pm->asb) ++ if (pm->asb || is_2712) + return devm_mfd_add_devices(dev, -1, bcm2835_power_devs, + ARRAY_SIZE(bcm2835_power_devs), + NULL, 0, NULL); + return 0; + } + +-static const struct of_device_id bcm2835_pm_of_match[] = { +- { .compatible = "brcm,bcm2835-pm-wdt", }, +- { .compatible = "brcm,bcm2835-pm", }, +- { .compatible = "brcm,bcm2711-pm", }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match); +- + static struct platform_driver bcm2835_pm_driver = { + .probe = bcm2835_pm_probe, + .driver = { diff --git a/target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch new file mode 100644 index 0000000000..e7e3652d91 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch @@ -0,0 +1,76 @@ +From 9cf85a95eeb239a079a3485bd1d0447431bdc7f1 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 8 Mar 2023 14:42:48 +0000 +Subject: [PATCH] soc: bcm: bcm2835-power: Add support for BCM2712 + +BCM2712 has a PM block but neither ASB nor RPIVID_ASB. Use the absence +of the "asb" register range to indicate BCM2712 and its different PM +register range. + +Signed-off-by: Phil Elwell +--- + drivers/soc/bcm/bcm2835-power.c | 29 +++++++++++++++++++---------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +--- a/drivers/soc/bcm/bcm2835-power.c ++++ b/drivers/soc/bcm/bcm2835-power.c +@@ -79,6 +79,7 @@ + #define PM_IMAGE 0x108 + #define PM_GRAFX 0x10c + #define PM_PROC 0x110 ++#define PM_GRAFX_2712 0x304 + #define PM_ENAB BIT(12) + #define PM_ISPRSTN BIT(8) + #define PM_H264RSTN BIT(7) +@@ -381,6 +382,9 @@ static int bcm2835_power_pd_power_on(str + return bcm2835_power_power_on(pd, PM_GRAFX); + + case BCM2835_POWER_DOMAIN_GRAFX_V3D: ++ if (!power->asb) ++ return bcm2835_asb_power_on(pd, PM_GRAFX_2712, ++ 0, 0, PM_V3DRSTN); + return bcm2835_asb_power_on(pd, PM_GRAFX, + ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, + PM_V3DRSTN); +@@ -447,6 +451,9 @@ static int bcm2835_power_pd_power_off(st + return bcm2835_power_power_off(pd, PM_GRAFX); + + case BCM2835_POWER_DOMAIN_GRAFX_V3D: ++ if (!power->asb) ++ return bcm2835_asb_power_off(pd, PM_GRAFX_2712, ++ 0, 0, PM_V3DRSTN); + return bcm2835_asb_power_off(pd, PM_GRAFX, + ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, + PM_V3DRSTN); +@@ -642,19 +649,21 @@ static int bcm2835_power_probe(struct pl + power->asb = pm->asb; + power->rpivid_asb = pm->rpivid_asb; + +- id = readl(power->asb + ASB_AXI_BRDG_ID); +- if (id != BCM2835_BRDG_ID /* "BRDG" */) { +- dev_err(dev, "ASB register ID returned 0x%08x\n", id); +- return -ENODEV; +- } +- +- if (power->rpivid_asb) { +- id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID); ++ if (power->asb) { ++ id = readl(power->asb + ASB_AXI_BRDG_ID); + if (id != BCM2835_BRDG_ID /* "BRDG" */) { +- dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n", +- id); ++ dev_err(dev, "ASB register ID returned 0x%08x\n", id); + return -ENODEV; + } ++ ++ if (power->rpivid_asb) { ++ id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID); ++ if (id != BCM2835_BRDG_ID /* "BRDG" */) { ++ dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n", ++ id); ++ return -ENODEV; ++ } ++ } + } + + power->pd_xlate.domains = devm_kcalloc(dev, diff --git a/target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch b/target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch new file mode 100644 index 0000000000..ff8471411f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch @@ -0,0 +1,150 @@ +From 380c336af070edf85826abbb0057bf92a03ec466 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 1 Mar 2023 17:57:11 +0000 +Subject: [PATCH] drivers: spi: Fix spi-gpio to correctly implement + sck-idle-input + +Formerly, if configured using DT, CS GPIOs were driven from spi.c +and it was possible for CS to be asserted (low) *before* starting +to drive SCK. CS GPIOs have been brought under control of this +driver in both ACPI and DT cases, with a fixup for GPIO polarity. + +Signed-off-by: Nick Hollinghurst +--- + drivers/spi/spi-gpio.c | 74 +++++++++++++++++++++++++++++------------- + 1 file changed, 51 insertions(+), 23 deletions(-) + +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -37,6 +37,7 @@ struct spi_gpio { + struct gpio_desc *mosi; + bool sck_idle_input; + struct gpio_desc **cs_gpios; ++ bool cs_dont_invert; + }; + + /*----------------------------------------------------------------------*/ +@@ -233,12 +234,18 @@ static void spi_gpio_chipselect(struct s + gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL); + } + +- /* Drive chip select line, if we have one */ ++ /* ++ * Drive chip select line, if we have one. ++ * SPI chip selects are normally active-low, but when ++ * cs_dont_invert is set, we assume their polarity is ++ * controlled by the GPIO, and write '1' to assert. ++ */ + if (spi_gpio->cs_gpios) { + struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select]; ++ int val = ((spi->mode & SPI_CS_HIGH) || spi_gpio->cs_dont_invert) ? ++ is_active : !is_active; + +- /* SPI chip selects are normally active-low */ +- gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); ++ gpiod_set_value_cansleep(cs, val); + } + + if (spi_gpio->sck_idle_input && !is_active) +@@ -254,12 +261,14 @@ static int spi_gpio_setup(struct spi_dev + /* + * The CS GPIOs have already been + * initialized from the descriptor lookup. ++ * Here we set them to the non-asserted state. + */ + if (spi_gpio->cs_gpios) { + cs = spi_gpio->cs_gpios[spi->chip_select]; + if (!spi->controller_state && cs) + status = gpiod_direction_output(cs, +- !(spi->mode & SPI_CS_HIGH)); ++ !((spi->mode & SPI_CS_HIGH) || ++ spi_gpio->cs_dont_invert)); + } + + if (!status) +@@ -336,6 +345,38 @@ static int spi_gpio_request(struct devic + return PTR_ERR_OR_ZERO(spi_gpio->sck); + } + ++/* ++ * In order to implement "sck-idle-input" (which requires SCK ++ * direction and CS level to be switched in a particular order), ++ * we need to control GPIO chip selects from within this driver. ++ */ ++ ++static int spi_gpio_probe_get_cs_gpios(struct device *dev, ++ struct spi_master *master, ++ bool gpio_defines_polarity) ++{ ++ int i; ++ struct spi_gpio *spi_gpio = spi_master_get_devdata(master); ++ ++ spi_gpio->cs_dont_invert = gpio_defines_polarity; ++ spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect, ++ sizeof(*spi_gpio->cs_gpios), ++ GFP_KERNEL); ++ if (!spi_gpio->cs_gpios) ++ return -ENOMEM; ++ ++ for (i = 0; i < master->num_chipselect; i++) { ++ spi_gpio->cs_gpios[i] = ++ devm_gpiod_get_index(dev, "cs", i, ++ gpio_defines_polarity ? ++ GPIOD_OUT_LOW : GPIOD_OUT_HIGH); ++ if (IS_ERR(spi_gpio->cs_gpios[i])) ++ return PTR_ERR(spi_gpio->cs_gpios[i]); ++ } ++ ++ return 0; ++} ++ + #ifdef CONFIG_OF + static const struct of_device_id spi_gpio_dt_ids[] = { + { .compatible = "spi-gpio" }, +@@ -346,10 +387,12 @@ MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids) + static int spi_gpio_probe_dt(struct platform_device *pdev, + struct spi_master *master) + { +- master->dev.of_node = pdev->dev.of_node; +- master->use_gpio_descriptors = true; ++ struct device *dev = &pdev->dev; + +- return 0; ++ master->dev.of_node = dev->of_node; ++ master->num_chipselect = gpiod_count(dev, "cs"); ++ ++ return spi_gpio_probe_get_cs_gpios(dev, master, true); + } + #else + static inline int spi_gpio_probe_dt(struct platform_device *pdev, +@@ -364,8 +407,6 @@ static int spi_gpio_probe_pdata(struct p + { + struct device *dev = &pdev->dev; + struct spi_gpio_platform_data *pdata = dev_get_platdata(dev); +- struct spi_gpio *spi_gpio = spi_master_get_devdata(master); +- int i; + + #ifdef GENERIC_BITBANG + if (!pdata || !pdata->num_chipselect) +@@ -377,20 +418,7 @@ static int spi_gpio_probe_pdata(struct p + */ + master->num_chipselect = pdata->num_chipselect ?: 1; + +- spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect, +- sizeof(*spi_gpio->cs_gpios), +- GFP_KERNEL); +- if (!spi_gpio->cs_gpios) +- return -ENOMEM; +- +- for (i = 0; i < master->num_chipselect; i++) { +- spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", i, +- GPIOD_OUT_HIGH); +- if (IS_ERR(spi_gpio->cs_gpios[i])) +- return PTR_ERR(spi_gpio->cs_gpios[i]); +- } +- +- return 0; ++ return spi_gpio_probe_get_cs_gpios(dev, master, false); + } + + static int spi_gpio_probe(struct platform_device *pdev) diff --git a/target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch b/target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch new file mode 100644 index 0000000000..1b7952ab18 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch @@ -0,0 +1,55 @@ +From 586f87307e75552292cfc6c76b81cd38d5ec31e2 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Mon, 4 Sep 2023 10:57:47 +0100 +Subject: [PATCH] spi: spi-gpio: Implement spidelay when requested bit rate <= + 1 Mbps + +Formerly the delay was omitted as bit-banged SPI seldom achieved +even one Mbit/s; but some modern platforms can run faster, and +some SPI devices may need to be clocked slower. + +Signed-off-by: Nick Hollinghurst +--- + drivers/spi/spi-gpio.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -11,12 +11,12 @@ + #include + #include + #include ++#include + + #include + #include + #include + +- + /* + * This bitbanging SPI master driver should help make systems usable + * when a native hardware SPI engine is not available, perhaps because +@@ -111,12 +111,18 @@ static inline int getmiso(const struct s + } + + /* +- * NOTE: this clocks "as fast as we can". It "should" be a function of the +- * requested device clock. Software overhead means we usually have trouble +- * reaching even one Mbit/sec (except when we can inline bitops), so for now +- * we'll just assume we never need additional per-bit slowdowns. ++ * Generic bit-banged GPIO SPI might free-run at something in the range ++ * 1Mbps ~ 10Mbps (depending on the platform), and some SPI devices may ++ * need to be clocked at a lower rate. ndelay() is often implemented by ++ * udelay() with rounding up, so do the delay only for nsecs >= 500 ++ * (<= 1Mbps). The conditional test adds a small overhead. + */ +-#define spidelay(nsecs) do {} while (0) ++ ++static inline void spidelay(unsigned long nsecs) ++{ ++ if (nsecs >= 500) ++ ndelay(nsecs); ++} + + #include "spi-bitbang-txrx.h" + diff --git a/target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch b/target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch new file mode 100644 index 0000000000..1a51a85660 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch @@ -0,0 +1,672 @@ +From 3f949caeef21269afc67dd62ae9826204f215934 Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +Date: Thu, 2 Mar 2023 11:49:46 +0100 +Subject: [PATCH] drm/v3d: fix up register addresses for V3D 7.x + +v2: fix kernel panic with debug-fs interface to list registers +--- + drivers/gpu/drm/v3d/v3d_debugfs.c | 177 +++++++++++++++++------------- + drivers/gpu/drm/v3d/v3d_gem.c | 3 + + drivers/gpu/drm/v3d/v3d_irq.c | 47 ++++---- + drivers/gpu/drm/v3d/v3d_regs.h | 51 ++++++++- + drivers/gpu/drm/v3d/v3d_sched.c | 41 ++++--- + 5 files changed, 204 insertions(+), 115 deletions(-) + +--- a/drivers/gpu/drm/v3d/v3d_debugfs.c ++++ b/drivers/gpu/drm/v3d/v3d_debugfs.c +@@ -13,69 +13,83 @@ + #include "v3d_drv.h" + #include "v3d_regs.h" + +-#define REGDEF(reg) { reg, #reg } ++#define REGDEF(min_ver, max_ver, reg) { min_ver, max_ver, reg, #reg } + struct v3d_reg_def { ++ u32 min_ver; ++ u32 max_ver; + u32 reg; + const char *name; + }; + + static const struct v3d_reg_def v3d_hub_reg_defs[] = { +- REGDEF(V3D_HUB_AXICFG), +- REGDEF(V3D_HUB_UIFCFG), +- REGDEF(V3D_HUB_IDENT0), +- REGDEF(V3D_HUB_IDENT1), +- REGDEF(V3D_HUB_IDENT2), +- REGDEF(V3D_HUB_IDENT3), +- REGDEF(V3D_HUB_INT_STS), +- REGDEF(V3D_HUB_INT_MSK_STS), +- +- REGDEF(V3D_MMU_CTL), +- REGDEF(V3D_MMU_VIO_ADDR), +- REGDEF(V3D_MMU_VIO_ID), +- REGDEF(V3D_MMU_DEBUG_INFO), ++ REGDEF(33, 42, V3D_HUB_AXICFG), ++ REGDEF(33, 71, V3D_HUB_UIFCFG), ++ REGDEF(33, 71, V3D_HUB_IDENT0), ++ REGDEF(33, 71, V3D_HUB_IDENT1), ++ REGDEF(33, 71, V3D_HUB_IDENT2), ++ REGDEF(33, 71, V3D_HUB_IDENT3), ++ REGDEF(33, 71, V3D_HUB_INT_STS), ++ REGDEF(33, 71, V3D_HUB_INT_MSK_STS), ++ ++ REGDEF(33, 71, V3D_MMU_CTL), ++ REGDEF(33, 71, V3D_MMU_VIO_ADDR), ++ REGDEF(33, 71, V3D_MMU_VIO_ID), ++ REGDEF(33, 71, V3D_MMU_DEBUG_INFO), ++ ++ REGDEF(71, 71, V3D_V7_GMP_STATUS), ++ REGDEF(71, 71, V3D_V7_GMP_CFG), ++ REGDEF(71, 71, V3D_V7_GMP_VIO_ADDR), + }; + + static const struct v3d_reg_def v3d_gca_reg_defs[] = { +- REGDEF(V3D_GCA_SAFE_SHUTDOWN), +- REGDEF(V3D_GCA_SAFE_SHUTDOWN_ACK), ++ REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN), ++ REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN_ACK), + }; + + static const struct v3d_reg_def v3d_core_reg_defs[] = { +- REGDEF(V3D_CTL_IDENT0), +- REGDEF(V3D_CTL_IDENT1), +- REGDEF(V3D_CTL_IDENT2), +- REGDEF(V3D_CTL_MISCCFG), +- REGDEF(V3D_CTL_INT_STS), +- REGDEF(V3D_CTL_INT_MSK_STS), +- REGDEF(V3D_CLE_CT0CS), +- REGDEF(V3D_CLE_CT0CA), +- REGDEF(V3D_CLE_CT0EA), +- REGDEF(V3D_CLE_CT1CS), +- REGDEF(V3D_CLE_CT1CA), +- REGDEF(V3D_CLE_CT1EA), +- +- REGDEF(V3D_PTB_BPCA), +- REGDEF(V3D_PTB_BPCS), +- +- REGDEF(V3D_GMP_STATUS), +- REGDEF(V3D_GMP_CFG), +- REGDEF(V3D_GMP_VIO_ADDR), +- +- REGDEF(V3D_ERR_FDBGO), +- REGDEF(V3D_ERR_FDBGB), +- REGDEF(V3D_ERR_FDBGS), +- REGDEF(V3D_ERR_STAT), ++ REGDEF(33, 71, V3D_CTL_IDENT0), ++ REGDEF(33, 71, V3D_CTL_IDENT1), ++ REGDEF(33, 71, V3D_CTL_IDENT2), ++ REGDEF(33, 71, V3D_CTL_MISCCFG), ++ REGDEF(33, 71, V3D_CTL_INT_STS), ++ REGDEF(33, 71, V3D_CTL_INT_MSK_STS), ++ REGDEF(33, 71, V3D_CLE_CT0CS), ++ REGDEF(33, 71, V3D_CLE_CT0CA), ++ REGDEF(33, 71, V3D_CLE_CT0EA), ++ REGDEF(33, 71, V3D_CLE_CT1CS), ++ REGDEF(33, 71, V3D_CLE_CT1CA), ++ REGDEF(33, 71, V3D_CLE_CT1EA), ++ ++ REGDEF(33, 71, V3D_PTB_BPCA), ++ REGDEF(33, 71, V3D_PTB_BPCS), ++ ++ REGDEF(33, 41, V3D_GMP_STATUS), ++ REGDEF(33, 41, V3D_GMP_CFG), ++ REGDEF(33, 41, V3D_GMP_VIO_ADDR), ++ ++ REGDEF(33, 71, V3D_ERR_FDBGO), ++ REGDEF(33, 71, V3D_ERR_FDBGB), ++ REGDEF(33, 71, V3D_ERR_FDBGS), ++ REGDEF(33, 71, V3D_ERR_STAT), + }; + + static const struct v3d_reg_def v3d_csd_reg_defs[] = { +- REGDEF(V3D_CSD_STATUS), +- REGDEF(V3D_CSD_CURRENT_CFG0), +- REGDEF(V3D_CSD_CURRENT_CFG1), +- REGDEF(V3D_CSD_CURRENT_CFG2), +- REGDEF(V3D_CSD_CURRENT_CFG3), +- REGDEF(V3D_CSD_CURRENT_CFG4), +- REGDEF(V3D_CSD_CURRENT_CFG5), +- REGDEF(V3D_CSD_CURRENT_CFG6), ++ REGDEF(41, 71, V3D_CSD_STATUS), ++ REGDEF(41, 41, V3D_CSD_CURRENT_CFG0), ++ REGDEF(41, 41, V3D_CSD_CURRENT_CFG1), ++ REGDEF(41, 41, V3D_CSD_CURRENT_CFG2), ++ REGDEF(41, 41, V3D_CSD_CURRENT_CFG3), ++ REGDEF(41, 41, V3D_CSD_CURRENT_CFG4), ++ REGDEF(41, 41, V3D_CSD_CURRENT_CFG5), ++ REGDEF(41, 41, V3D_CSD_CURRENT_CFG6), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG0), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG1), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG2), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG3), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG4), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG5), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG6), ++ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG7), + }; + + static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused) +@@ -86,38 +100,41 @@ static int v3d_v3d_debugfs_regs(struct s + int i, core; + + for (i = 0; i < ARRAY_SIZE(v3d_hub_reg_defs); i++) { +- seq_printf(m, "%s (0x%04x): 0x%08x\n", +- v3d_hub_reg_defs[i].name, v3d_hub_reg_defs[i].reg, +- V3D_READ(v3d_hub_reg_defs[i].reg)); ++ const struct v3d_reg_def *def = &v3d_hub_reg_defs[i]; ++ ++ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) { ++ seq_printf(m, "%s (0x%04x): 0x%08x\n", ++ def->name, def->reg, V3D_READ(def->reg)); ++ } + } + +- if (v3d->ver < 41) { +- for (i = 0; i < ARRAY_SIZE(v3d_gca_reg_defs); i++) { ++ for (i = 0; i < ARRAY_SIZE(v3d_gca_reg_defs); i++) { ++ const struct v3d_reg_def *def = &v3d_gca_reg_defs[i]; ++ ++ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) { + seq_printf(m, "%s (0x%04x): 0x%08x\n", +- v3d_gca_reg_defs[i].name, +- v3d_gca_reg_defs[i].reg, +- V3D_GCA_READ(v3d_gca_reg_defs[i].reg)); ++ def->name, def->reg, V3D_GCA_READ(def->reg)); + } + } + + for (core = 0; core < v3d->cores; core++) { + for (i = 0; i < ARRAY_SIZE(v3d_core_reg_defs); i++) { +- seq_printf(m, "core %d %s (0x%04x): 0x%08x\n", +- core, +- v3d_core_reg_defs[i].name, +- v3d_core_reg_defs[i].reg, +- V3D_CORE_READ(core, +- v3d_core_reg_defs[i].reg)); ++ const struct v3d_reg_def *def = &v3d_core_reg_defs[i]; ++ ++ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) { ++ seq_printf(m, "core %d %s (0x%04x): 0x%08x\n", ++ core, def->name, def->reg, ++ V3D_CORE_READ(core, def->reg)); ++ } + } + +- if (v3d_has_csd(v3d)) { +- for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) { ++ for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) { ++ const struct v3d_reg_def *def = &v3d_csd_reg_defs[i]; ++ ++ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) { + seq_printf(m, "core %d %s (0x%04x): 0x%08x\n", +- core, +- v3d_csd_reg_defs[i].name, +- v3d_csd_reg_defs[i].reg, +- V3D_CORE_READ(core, +- v3d_csd_reg_defs[i].reg)); ++ core, def->name, def->reg, ++ V3D_CORE_READ(core, def->reg)); + } + } + } +@@ -148,8 +165,10 @@ static int v3d_v3d_debugfs_ident(struct + str_yes_no(ident2 & V3D_HUB_IDENT2_WITH_MMU)); + seq_printf(m, "TFU: %s\n", + str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TFU)); +- seq_printf(m, "TSY: %s\n", +- str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TSY)); ++ if (v3d->ver <= 42) { ++ seq_printf(m, "TSY: %s\n", ++ str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TSY)); ++ } + seq_printf(m, "MSO: %s\n", + str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_MSO)); + seq_printf(m, "L3C: %s (%dkb)\n", +@@ -178,10 +197,14 @@ static int v3d_v3d_debugfs_ident(struct + seq_printf(m, " QPUs: %d\n", nslc * qups); + seq_printf(m, " Semaphores: %d\n", + V3D_GET_FIELD(ident1, V3D_IDENT1_NSEM)); +- seq_printf(m, " BCG int: %d\n", +- (ident2 & V3D_IDENT2_BCG_INT) != 0); +- seq_printf(m, " Override TMU: %d\n", +- (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0); ++ if (v3d->ver <= 42) { ++ seq_printf(m, " BCG int: %d\n", ++ (ident2 & V3D_IDENT2_BCG_INT) != 0); ++ } ++ if (v3d->ver < 40) { ++ seq_printf(m, " Override TMU: %d\n", ++ (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0); ++ } + } + + return 0; +@@ -289,8 +312,10 @@ static int v3d_measure_clock(struct seq_ + int measure_ms = 1000; + + if (v3d->ver >= 40) { ++ int cycle_count_reg = v3d->ver < 71 ? ++ V3D_PCTR_CYCLE_COUNT : V3D_V7_PCTR_CYCLE_COUNT; + V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3, +- V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT, ++ V3D_SET_FIELD(cycle_count_reg, + V3D_PCTR_S0)); + V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1); + V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1); +--- a/drivers/gpu/drm/v3d/v3d_gem.c ++++ b/drivers/gpu/drm/v3d/v3d_gem.c +@@ -88,6 +88,9 @@ v3d_init_hw_state(struct v3d_dev *v3d) + static void + v3d_idle_axi(struct v3d_dev *v3d, int core) + { ++ if (v3d->ver >= 71) ++ return; ++ + V3D_CORE_WRITE(core, V3D_GMP_CFG, V3D_GMP_CFG_STOP_REQ); + + if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS) & +--- a/drivers/gpu/drm/v3d/v3d_irq.c ++++ b/drivers/gpu/drm/v3d/v3d_irq.c +@@ -20,16 +20,17 @@ + #include "v3d_regs.h" + #include "v3d_trace.h" + +-#define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \ +- V3D_INT_FLDONE | \ +- V3D_INT_FRDONE | \ +- V3D_INT_CSDDONE | \ +- V3D_INT_GMPV)) +- +-#define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \ +- V3D_HUB_INT_MMU_PTI | \ +- V3D_HUB_INT_MMU_CAP | \ +- V3D_HUB_INT_TFUC)) ++#define V3D_CORE_IRQS(ver) ((u32)(V3D_INT_OUTOMEM | \ ++ V3D_INT_FLDONE | \ ++ V3D_INT_FRDONE | \ ++ (ver < 71 ? V3D_INT_CSDDONE : V3D_V7_INT_CSDDONE) | \ ++ (ver < 71 ? V3D_INT_GMPV : 0))) ++ ++#define V3D_HUB_IRQS(ver) ((u32)(V3D_HUB_INT_MMU_WRV | \ ++ V3D_HUB_INT_MMU_PTI | \ ++ V3D_HUB_INT_MMU_CAP | \ ++ V3D_HUB_INT_TFUC | \ ++ (ver >= 71 ? V3D_V7_HUB_INT_GMPV : 0))) + + static irqreturn_t + v3d_hub_irq(int irq, void *arg); +@@ -118,7 +119,8 @@ v3d_irq(int irq, void *arg) + status = IRQ_HANDLED; + } + +- if (intsts & V3D_INT_CSDDONE) { ++ if ((v3d->ver < 71 && (intsts & V3D_INT_CSDDONE)) || ++ (v3d->ver >= 71 && (intsts & V3D_V7_INT_CSDDONE))) { + struct v3d_fence *fence = + to_v3d_fence(v3d->csd_job->base.irq_fence); + v3d->gpu_queue_stats[V3D_CSD].last_exec_end = local_clock(); +@@ -131,7 +133,7 @@ v3d_irq(int irq, void *arg) + /* We shouldn't be triggering these if we have GMP in + * always-allowed mode. + */ +- if (intsts & V3D_INT_GMPV) ++ if (v3d->ver < 71 && (intsts & V3D_INT_GMPV)) + dev_err(v3d->drm.dev, "GMP violation\n"); + + /* V3D 4.2 wires the hub and core IRQs together, so if we & +@@ -205,6 +207,11 @@ v3d_hub_irq(int irq, void *arg) + status = IRQ_HANDLED; + } + ++ if (v3d->ver >= 71 && intsts & V3D_V7_HUB_INT_GMPV) { ++ dev_err(v3d->drm.dev, "GMP Violation\n"); ++ status = IRQ_HANDLED; ++ } ++ + return status; + } + +@@ -219,8 +226,8 @@ v3d_irq_init(struct v3d_dev *v3d) + * for us. + */ + for (core = 0; core < v3d->cores; core++) +- V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS); +- V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS); ++ V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver)); ++ V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS(v3d->ver)); + + irq1 = platform_get_irq_optional(v3d_to_pdev(v3d), 1); + if (irq1 == -EPROBE_DEFER) +@@ -264,12 +271,12 @@ v3d_irq_enable(struct v3d_dev *v3d) + + /* Enable our set of interrupts, masking out any others. */ + for (core = 0; core < v3d->cores; core++) { +- V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~V3D_CORE_IRQS); +- V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_CLR, V3D_CORE_IRQS); ++ V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~V3D_CORE_IRQS(v3d->ver)); ++ V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_CLR, V3D_CORE_IRQS(v3d->ver)); + } + +- V3D_WRITE(V3D_HUB_INT_MSK_SET, ~V3D_HUB_IRQS); +- V3D_WRITE(V3D_HUB_INT_MSK_CLR, V3D_HUB_IRQS); ++ V3D_WRITE(V3D_HUB_INT_MSK_SET, ~V3D_HUB_IRQS(v3d->ver)); ++ V3D_WRITE(V3D_HUB_INT_MSK_CLR, V3D_HUB_IRQS(v3d->ver)); + } + + void +@@ -284,8 +291,8 @@ v3d_irq_disable(struct v3d_dev *v3d) + + /* Clear any pending interrupts we might have left. */ + for (core = 0; core < v3d->cores; core++) +- V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS); +- V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS); ++ V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver)); ++ V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS(v3d->ver)); + + cancel_work_sync(&v3d->overflow_mem_work); + } +--- a/drivers/gpu/drm/v3d/v3d_regs.h ++++ b/drivers/gpu/drm/v3d/v3d_regs.h +@@ -57,6 +57,7 @@ + #define V3D_HUB_INT_MSK_STS 0x0005c + #define V3D_HUB_INT_MSK_SET 0x00060 + #define V3D_HUB_INT_MSK_CLR 0x00064 ++# define V3D_V7_HUB_INT_GMPV BIT(6) + # define V3D_HUB_INT_MMU_WRV BIT(5) + # define V3D_HUB_INT_MMU_PTI BIT(4) + # define V3D_HUB_INT_MMU_CAP BIT(3) +@@ -64,6 +65,7 @@ + # define V3D_HUB_INT_TFUC BIT(1) + # define V3D_HUB_INT_TFUF BIT(0) + ++/* GCA registers only exist in V3D < 41 */ + #define V3D_GCA_CACHE_CTRL 0x0000c + # define V3D_GCA_CACHE_CTRL_FLUSH BIT(0) + +@@ -87,6 +89,7 @@ + # define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0) + + #define V3D_TFU_CS 0x00400 ++#define V3D_V7_TFU_CS 0x00700 + /* Stops current job, empties input fifo. */ + # define V3D_TFU_CS_TFURST BIT(31) + # define V3D_TFU_CS_CVTCT_MASK V3D_MASK(23, 16) +@@ -96,6 +99,7 @@ + # define V3D_TFU_CS_BUSY BIT(0) + + #define V3D_TFU_SU 0x00404 ++#define V3D_V7_TFU_SU 0x00704 + /* Interrupt when FINTTHR input slots are free (0 = disabled) */ + # define V3D_TFU_SU_FINTTHR_MASK V3D_MASK(13, 8) + # define V3D_TFU_SU_FINTTHR_SHIFT 8 +@@ -107,38 +111,53 @@ + # define V3D_TFU_SU_THROTTLE_SHIFT 0 + + #define V3D_TFU_ICFG 0x00408 ++#define V3D_V7_TFU_ICFG 0x00708 + /* Interrupt when the conversion is complete. */ + # define V3D_TFU_ICFG_IOC BIT(0) + + /* Input Image Address */ + #define V3D_TFU_IIA 0x0040c ++#define V3D_V7_TFU_IIA 0x0070c + /* Input Chroma Address */ + #define V3D_TFU_ICA 0x00410 ++#define V3D_V7_TFU_ICA 0x00710 + /* Input Image Stride */ + #define V3D_TFU_IIS 0x00414 ++#define V3D_V7_TFU_IIS 0x00714 + /* Input Image U-Plane Address */ + #define V3D_TFU_IUA 0x00418 ++#define V3D_V7_TFU_IUA 0x00718 ++/* Image output config (VD 7.x only) */ ++#define V3D_V7_TFU_IOC 0x0071c + /* Output Image Address */ + #define V3D_TFU_IOA 0x0041c ++#define V3D_V7_TFU_IOA 0x00720 + /* Image Output Size */ + #define V3D_TFU_IOS 0x00420 ++#define V3D_V7_TFU_IOS 0x00724 + /* TFU YUV Coefficient 0 */ + #define V3D_TFU_COEF0 0x00424 +-/* Use these regs instead of the defaults. */ ++#define V3D_V7_TFU_COEF0 0x00728 ++/* Use these regs instead of the defaults (V3D 4.x only) */ + # define V3D_TFU_COEF0_USECOEF BIT(31) + /* TFU YUV Coefficient 1 */ + #define V3D_TFU_COEF1 0x00428 ++#define V3D_V7_TFU_COEF1 0x0072c + /* TFU YUV Coefficient 2 */ + #define V3D_TFU_COEF2 0x0042c ++#define V3D_V7_TFU_COEF2 0x00730 + /* TFU YUV Coefficient 3 */ + #define V3D_TFU_COEF3 0x00430 ++#define V3D_V7_TFU_COEF3 0x00734 + ++/* V3D 4.x only */ + #define V3D_TFU_CRC 0x00434 + + /* Per-MMU registers. */ + + #define V3D_MMUC_CONTROL 0x01000 + # define V3D_MMUC_CONTROL_CLEAR BIT(3) ++# define V3D_V7_MMUC_CONTROL_CLEAR BIT(11) + # define V3D_MMUC_CONTROL_FLUSHING BIT(2) + # define V3D_MMUC_CONTROL_FLUSH BIT(1) + # define V3D_MMUC_CONTROL_ENABLE BIT(0) +@@ -246,7 +265,6 @@ + + #define V3D_CTL_L2TCACTL 0x00030 + # define V3D_L2TCACTL_TMUWCF BIT(8) +-# define V3D_L2TCACTL_L2T_NO_WM BIT(4) + /* Invalidates cache lines. */ + # define V3D_L2TCACTL_FLM_FLUSH 0 + /* Removes cachelines without writing dirty lines back. */ +@@ -268,7 +286,9 @@ + # define V3D_INT_QPU_MASK V3D_MASK(27, 16) + # define V3D_INT_QPU_SHIFT 16 + # define V3D_INT_CSDDONE BIT(7) ++# define V3D_V7_INT_CSDDONE BIT(6) + # define V3D_INT_PCTR BIT(6) ++# define V3D_V7_INT_PCTR BIT(5) + # define V3D_INT_GMPV BIT(5) + # define V3D_INT_TRFB BIT(4) + # define V3D_INT_SPILLUSE BIT(3) +@@ -350,14 +370,19 @@ + #define V3D_V4_PCTR_0_SRC_X(x) (V3D_V4_PCTR_0_SRC_0_3 + \ + 4 * (x)) + # define V3D_PCTR_S0_MASK V3D_MASK(6, 0) ++# define V3D_V7_PCTR_S0_MASK V3D_MASK(7, 0) + # define V3D_PCTR_S0_SHIFT 0 + # define V3D_PCTR_S1_MASK V3D_MASK(14, 8) ++# define V3D_V7_PCTR_S1_MASK V3D_MASK(15, 8) + # define V3D_PCTR_S1_SHIFT 8 + # define V3D_PCTR_S2_MASK V3D_MASK(22, 16) ++# define V3D_V7_PCTR_S2_MASK V3D_MASK(23, 16) + # define V3D_PCTR_S2_SHIFT 16 + # define V3D_PCTR_S3_MASK V3D_MASK(30, 24) ++# define V3D_V7_PCTR_S3_MASK V3D_MASK(31, 24) + # define V3D_PCTR_S3_SHIFT 24 + # define V3D_PCTR_CYCLE_COUNT 32 ++# define V3D_V7_PCTR_CYCLE_COUNT 0 + + /* Output values of the counters. */ + #define V3D_PCTR_0_PCTR0 0x00680 +@@ -365,6 +390,7 @@ + #define V3D_PCTR_0_PCTRX(x) (V3D_PCTR_0_PCTR0 + \ + 4 * (x)) + #define V3D_GMP_STATUS 0x00800 ++#define V3D_V7_GMP_STATUS 0x00600 + # define V3D_GMP_STATUS_GMPRST BIT(31) + # define V3D_GMP_STATUS_WR_COUNT_MASK V3D_MASK(30, 24) + # define V3D_GMP_STATUS_WR_COUNT_SHIFT 24 +@@ -378,12 +404,14 @@ + # define V3D_GMP_STATUS_VIO BIT(0) + + #define V3D_GMP_CFG 0x00804 ++#define V3D_V7_GMP_CFG 0x00604 + # define V3D_GMP_CFG_LBURSTEN BIT(3) + # define V3D_GMP_CFG_PGCRSEN BIT() + # define V3D_GMP_CFG_STOP_REQ BIT(1) + # define V3D_GMP_CFG_PROT_ENABLE BIT(0) + + #define V3D_GMP_VIO_ADDR 0x00808 ++#define V3D_V7_GMP_VIO_ADDR 0x00608 + #define V3D_GMP_VIO_TYPE 0x0080c + #define V3D_GMP_TABLE_ADDR 0x00810 + #define V3D_GMP_CLEAR_LOAD 0x00814 +@@ -399,24 +427,28 @@ + # define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH BIT(0) + + #define V3D_CSD_QUEUED_CFG0 0x00904 ++#define V3D_V7_CSD_QUEUED_CFG0 0x00930 + # define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK V3D_MASK(31, 16) + # define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT 16 + # define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_MASK V3D_MASK(15, 0) + # define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_SHIFT 0 + + #define V3D_CSD_QUEUED_CFG1 0x00908 ++#define V3D_V7_CSD_QUEUED_CFG1 0x00934 + # define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_MASK V3D_MASK(31, 16) + # define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_SHIFT 16 + # define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_MASK V3D_MASK(15, 0) + # define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_SHIFT 0 + + #define V3D_CSD_QUEUED_CFG2 0x0090c ++#define V3D_V7_CSD_QUEUED_CFG2 0x00938 + # define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_MASK V3D_MASK(31, 16) + # define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_SHIFT 16 + # define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_MASK V3D_MASK(15, 0) + # define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_SHIFT 0 + + #define V3D_CSD_QUEUED_CFG3 0x00910 ++#define V3D_V7_CSD_QUEUED_CFG3 0x0093c + # define V3D_CSD_QUEUED_CFG3_OVERLAP_WITH_PREV BIT(26) + # define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_MASK V3D_MASK(25, 20) + # define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_SHIFT 20 +@@ -429,22 +461,36 @@ + + /* Number of batches, minus 1 */ + #define V3D_CSD_QUEUED_CFG4 0x00914 ++#define V3D_V7_CSD_QUEUED_CFG4 0x00940 + + /* Shader address, pnan, singleseg, threading, like a shader record. */ + #define V3D_CSD_QUEUED_CFG5 0x00918 ++#define V3D_V7_CSD_QUEUED_CFG5 0x00944 + + /* Uniforms address (4 byte aligned) */ + #define V3D_CSD_QUEUED_CFG6 0x0091c ++#define V3D_V7_CSD_QUEUED_CFG6 0x00948 ++ ++#define V3D_V7_CSD_QUEUED_CFG7 0x0094c + + #define V3D_CSD_CURRENT_CFG0 0x00920 ++#define V3D_V7_CSD_CURRENT_CFG0 0x00958 + #define V3D_CSD_CURRENT_CFG1 0x00924 ++#define V3D_V7_CSD_CURRENT_CFG1 0x0095c + #define V3D_CSD_CURRENT_CFG2 0x00928 ++#define V3D_V7_CSD_CURRENT_CFG2 0x00960 + #define V3D_CSD_CURRENT_CFG3 0x0092c ++#define V3D_V7_CSD_CURRENT_CFG3 0x00964 + #define V3D_CSD_CURRENT_CFG4 0x00930 ++#define V3D_V7_CSD_CURRENT_CFG4 0x00968 + #define V3D_CSD_CURRENT_CFG5 0x00934 ++#define V3D_V7_CSD_CURRENT_CFG5 0x0096c + #define V3D_CSD_CURRENT_CFG6 0x00938 ++#define V3D_V7_CSD_CURRENT_CFG6 0x00970 ++#define V3D_V7_CSD_CURRENT_CFG7 0x00974 + + #define V3D_CSD_CURRENT_ID0 0x0093c ++#define V3D_V7_CSD_CURRENT_ID0 0x00978 + # define V3D_CSD_CURRENT_ID0_WG_X_MASK V3D_MASK(31, 16) + # define V3D_CSD_CURRENT_ID0_WG_X_SHIFT 16 + # define V3D_CSD_CURRENT_ID0_WG_IN_SG_MASK V3D_MASK(11, 8) +@@ -453,6 +499,7 @@ + # define V3D_CSD_CURRENT_ID0_L_IDX_SHIFT 0 + + #define V3D_CSD_CURRENT_ID1 0x00940 ++#define V3D_V7_CSD_CURRENT_ID1 0x0097c + # define V3D_CSD_CURRENT_ID0_WG_Z_MASK V3D_MASK(31, 16) + # define V3D_CSD_CURRENT_ID0_WG_Z_SHIFT 16 + # define V3D_CSD_CURRENT_ID0_WG_Y_MASK V3D_MASK(15, 0) +--- a/drivers/gpu/drm/v3d/v3d_sched.c ++++ b/drivers/gpu/drm/v3d/v3d_sched.c +@@ -282,6 +282,8 @@ static struct dma_fence *v3d_render_job_ + return fence; + } + ++#define V3D_TFU_REG(name) ((v3d->ver < 71) ? V3D_TFU_ ## name : V3D_V7_TFU_ ## name) ++ + static struct dma_fence * + v3d_tfu_job_run(struct drm_sched_job *sched_job) + { +@@ -302,20 +304,22 @@ v3d_tfu_job_run(struct drm_sched_job *sc + trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno); + + v3d_sched_stats_add_job(&v3d->gpu_queue_stats[V3D_TFU], sched_job); +- V3D_WRITE(V3D_TFU_IIA, job->args.iia); +- V3D_WRITE(V3D_TFU_IIS, job->args.iis); +- V3D_WRITE(V3D_TFU_ICA, job->args.ica); +- V3D_WRITE(V3D_TFU_IUA, job->args.iua); +- V3D_WRITE(V3D_TFU_IOA, job->args.ioa); +- V3D_WRITE(V3D_TFU_IOS, job->args.ios); +- V3D_WRITE(V3D_TFU_COEF0, job->args.coef[0]); +- if (job->args.coef[0] & V3D_TFU_COEF0_USECOEF) { +- V3D_WRITE(V3D_TFU_COEF1, job->args.coef[1]); +- V3D_WRITE(V3D_TFU_COEF2, job->args.coef[2]); +- V3D_WRITE(V3D_TFU_COEF3, job->args.coef[3]); ++ V3D_WRITE(V3D_TFU_REG(IIA), job->args.iia); ++ V3D_WRITE(V3D_TFU_REG(IIS), job->args.iis); ++ V3D_WRITE(V3D_TFU_REG(ICA), job->args.ica); ++ V3D_WRITE(V3D_TFU_REG(IUA), job->args.iua); ++ V3D_WRITE(V3D_TFU_REG(IOA), job->args.ioa); ++ if (v3d->ver >= 71) ++ V3D_WRITE(V3D_V7_TFU_IOC, job->args.v71.ioc); ++ V3D_WRITE(V3D_TFU_REG(IOS), job->args.ios); ++ V3D_WRITE(V3D_TFU_REG(COEF0), job->args.coef[0]); ++ if (v3d->ver >= 71 || (job->args.coef[0] & V3D_TFU_COEF0_USECOEF)) { ++ V3D_WRITE(V3D_TFU_REG(COEF1), job->args.coef[1]); ++ V3D_WRITE(V3D_TFU_REG(COEF2), job->args.coef[2]); ++ V3D_WRITE(V3D_TFU_REG(COEF3), job->args.coef[3]); + } + /* ICFG kicks off the job. */ +- V3D_WRITE(V3D_TFU_ICFG, job->args.icfg | V3D_TFU_ICFG_IOC); ++ V3D_WRITE(V3D_TFU_REG(ICFG), job->args.icfg | V3D_TFU_ICFG_IOC); + + return fence; + } +@@ -327,7 +331,7 @@ v3d_csd_job_run(struct drm_sched_job *sc + struct v3d_dev *v3d = job->base.v3d; + struct drm_device *dev = &v3d->drm; + struct dma_fence *fence; +- int i; ++ int i, csd_cfg0_reg, csd_cfg_reg_count; + + v3d->csd_job = job; + +@@ -346,10 +350,12 @@ v3d_csd_job_run(struct drm_sched_job *sc + v3d_sched_stats_add_job(&v3d->gpu_queue_stats[V3D_CSD], sched_job); + v3d_switch_perfmon(v3d, &job->base); + +- for (i = 1; i <= 6; i++) +- V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]); ++ csd_cfg0_reg = v3d->ver < 71 ? V3D_CSD_QUEUED_CFG0 : V3D_V7_CSD_QUEUED_CFG0; ++ csd_cfg_reg_count = v3d->ver < 71 ? 6 : 7; ++ for (i = 1; i <= csd_cfg_reg_count; i++) ++ V3D_CORE_WRITE(0, csd_cfg0_reg + 4 * i, job->args.cfg[i]); + /* CFG0 write kicks off the job. */ +- V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0, job->args.cfg[0]); ++ V3D_CORE_WRITE(0, csd_cfg0_reg, job->args.cfg[0]); + + return fence; + } +@@ -452,7 +458,8 @@ v3d_csd_job_timedout(struct drm_sched_jo + { + struct v3d_csd_job *job = to_csd_job(sched_job); + struct v3d_dev *v3d = job->base.v3d; +- u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4); ++ u32 batches = V3D_CORE_READ(0, (v3d->ver < 71 ? V3D_CSD_CURRENT_CFG4 : ++ V3D_V7_CSD_CURRENT_CFG4)); + + /* If we've made progress, skip reset and let the timer get + * rearmed. diff --git a/target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch b/target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch new file mode 100644 index 0000000000..ed1d5f05df --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch @@ -0,0 +1,24 @@ +From 22fb30936524ae96151789741885edbc45efb53d Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +Date: Thu, 2 Mar 2023 11:52:08 +0100 +Subject: [PATCH] drm/v3d: update UAPI to match user-space for V3D 7.x + +V3D t.x takes a new parameter to configure TFU jobs that needs +to be provided by user space. +--- + include/uapi/drm/v3d_drm.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/include/uapi/drm/v3d_drm.h ++++ b/include/uapi/drm/v3d_drm.h +@@ -319,6 +319,10 @@ struct drm_v3d_submit_tfu { + + /* Pointer to an array of ioctl extensions*/ + __u64 extensions; ++ ++ struct { ++ __u32 ioc; ++ } v71; + }; + + /* Submits a compute shader for dispatch. This job will block on any diff --git a/target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch b/target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch new file mode 100644 index 0000000000..64189338e6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch @@ -0,0 +1,19 @@ +From 18bc419d38eda06ded78c7b702c0e21e5af8f24c Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +Date: Thu, 2 Mar 2023 11:54:45 +0100 +Subject: [PATCH] drm/v3d: add brcm,2712-v3d as a compatible V3D device + +--- + drivers/gpu/drm/v3d/v3d_drv.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/v3d/v3d_drv.c ++++ b/drivers/gpu/drm/v3d/v3d_drv.c +@@ -193,6 +193,7 @@ static const struct drm_driver v3d_drm_d + }; + + static const struct of_device_id v3d_of_match[] = { ++ { .compatible = "brcm,2712-v3d" }, + { .compatible = "brcm,2711-v3d" }, + { .compatible = "brcm,7268-v3d" }, + { .compatible = "brcm,7278-v3d" }, diff --git a/target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch b/target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch new file mode 100644 index 0000000000..3c53996ff0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch @@ -0,0 +1,64 @@ +From 12c7ea43b930976f35ce75d11fd3f55438868e13 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 4 Aug 2023 11:26:10 +0100 +Subject: [PATCH] drm/v3d: Improve MMU support for larger pages + +The built-in MMU driver went most of the way towards supporting larger +kernel pages, but dropped the ball when it comes to calculating indexes +into the page table. Fix it. + +Signed-off-by: Phil Elwell +--- + drivers/gpu/drm/v3d/v3d_mmu.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/v3d/v3d_mmu.c ++++ b/drivers/gpu/drm/v3d/v3d_mmu.c +@@ -22,6 +22,7 @@ + #include "v3d_regs.h" + + #define V3D_MMU_PAGE_SHIFT 12 ++#define V3D_PAGE_FACTOR (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) + + /* Note: All PTEs for the 1MB superpage must be filled with the + * superpage bit set. +@@ -88,7 +89,7 @@ void v3d_mmu_insert_ptes(struct v3d_bo * + { + struct drm_gem_shmem_object *shmem_obj = &bo->base; + struct v3d_dev *v3d = to_v3d_dev(shmem_obj->base.dev); +- u32 page = bo->node.start; ++ u32 page = bo->node.start * V3D_PAGE_FACTOR; + u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID; + struct sg_dma_page_iter dma_iter; + +@@ -98,13 +99,13 @@ void v3d_mmu_insert_ptes(struct v3d_bo * + u32 pte = page_prot | page_address; + u32 i; + +- BUG_ON(page_address + (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) >= ++ BUG_ON(page_address + V3D_PAGE_FACTOR >= + BIT(24)); +- for (i = 0; i < PAGE_SIZE >> V3D_MMU_PAGE_SHIFT; i++) ++ for (i = 0; i < V3D_PAGE_FACTOR; i++) + v3d->pt[page++] = pte + i; + } + +- WARN_ON_ONCE(page - bo->node.start != ++ WARN_ON_ONCE(page - (bo->node.start * V3D_PAGE_FACTOR) != + shmem_obj->base.size >> V3D_MMU_PAGE_SHIFT); + + if (v3d_mmu_flush_all(v3d)) +@@ -115,10 +116,10 @@ void v3d_mmu_remove_ptes(struct v3d_bo * + { + struct v3d_dev *v3d = to_v3d_dev(bo->base.base.dev); + u32 npages = bo->base.base.size >> V3D_MMU_PAGE_SHIFT; +- u32 page; ++ u32 page = bo->node.start * V3D_PAGE_FACTOR; + +- for (page = bo->node.start; page < bo->node.start + npages; page++) +- v3d->pt[page] = 0; ++ while (npages--) ++ v3d->pt[page++] = 0; + + if (v3d_mmu_flush_all(v3d)) + dev_err(v3d->drm.dev, "MMU flush timeout\n"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch b/target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch new file mode 100644 index 0000000000..43c5c395c9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch @@ -0,0 +1,19 @@ +From 5970fa51663511d7f773db7109ff6fa2504f186a Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +Date: Thu, 2 Mar 2023 11:56:52 +0100 +Subject: [PATCH] dt-bindings: gpu: v3d: Add BCM2712 to compatibility list + +--- + Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml ++++ b/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml +@@ -16,6 +16,7 @@ properties: + + compatible: + enum: ++ - brcm,2712-v3d + - brcm,2711-v3d + - brcm,7268-v3d + - brcm,7278-v3d diff --git a/target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch new file mode 100644 index 0000000000..14e6b0a9e4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch @@ -0,0 +1,328 @@ +From fdf9cab5eaa849e90b12e17718bc47130a91433c Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Tue, 25 Apr 2023 15:52:13 +0100 +Subject: [PATCH] drivers: char: add generic gpiomem driver + +Based on bcm2835-gpiomem. + +We allow export of the "GPIO registers" to userspace via a chardev as +this allows for finer access control (e.g. users must be group gpio, root +not required). + +This driver allows access to either rp1-gpiomem or gpiomem, depending on +which nodes are populated in devicetree. + +RP1 has a different look-and-feel to BCM283x SoCs as it has split ranges +for IO controls and the parallel registered OE/IN/OUT access. To handle +this, the driver concatenates the ranges for an IO bank and the +corresponding RIO instance into a contiguous buffer. + +Signed-off-by: Jonathan Bell +--- + drivers/char/Kconfig | 8 + + drivers/char/Makefile | 1 + + drivers/char/raspberrypi-gpiomem.c | 276 +++++++++++++++++++++++++++++ + 3 files changed, 285 insertions(+) + create mode 100644 drivers/char/raspberrypi-gpiomem.c + +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -461,4 +461,12 @@ config RANDOM_TRUST_BOOTLOADER + believe its RNG facilities may be faulty. This may also be configured + at boot time with "random.trust_bootloader=on/off". + ++config RASPBERRYPI_GPIOMEM ++ tristate "Rootless GPIO access via mmap() on Raspberry Pi boards" ++ default n ++ help ++ Provides users with root-free access to the GPIO registers ++ on the board. Calling mmap(/dev/gpiomem) will map the GPIO ++ register page to the user's pointer. ++ + endmenu +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -46,3 +46,4 @@ obj-$(CONFIG_XILLYBUS_CLASS) += xillybus + obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o + obj-$(CONFIG_ADI) += adi.o + obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/ ++obj-$(CONFIG_RASPBERRYPI_GPIOMEM) += raspberrypi-gpiomem.o +--- /dev/null ++++ b/drivers/char/raspberrypi-gpiomem.c +@@ -0,0 +1,276 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/** ++ * raspberrypi-gpiomem.c ++ * ++ * Provides MMIO access to discontiguous section of Device memory as a linear ++ * user mapping. Successor to bcm2835-gpiomem.c. ++ * ++ * Copyright (c) 2023, Raspberry Pi Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "rpi-gpiomem" ++#define DEVICE_MINOR 0 ++ ++/* ++ * Sensible max for a hypothetical "gpio" controller that splits pads, ++ * IO controls, GPIO in/out/enable, and function selection into different ++ * ranges. Most use only one or two. ++ */ ++#define MAX_RANGES 4 ++ ++struct io_windows { ++ unsigned long phys_base; ++ unsigned long len; ++}; ++ ++struct rpi_gpiomem_priv { ++ dev_t devid; ++ struct class *class; ++ struct cdev rpi_gpiomem_cdev; ++ struct device *dev; ++ const char *name; ++ unsigned int nr_wins; ++ struct io_windows iowins[4]; ++}; ++ ++static int rpi_gpiomem_open(struct inode *inode, struct file *file) ++{ ++ int dev = iminor(inode); ++ int ret = 0; ++ struct rpi_gpiomem_priv *priv; ++ ++ if (dev != DEVICE_MINOR) ++ ret = -ENXIO; ++ ++ priv = container_of(inode->i_cdev, struct rpi_gpiomem_priv, ++ rpi_gpiomem_cdev); ++ if (!priv) ++ return -EINVAL; ++ file->private_data = priv; ++ return ret; ++} ++ ++static int rpi_gpiomem_release(struct inode *inode, struct file *file) ++{ ++ int dev = iminor(inode); ++ int ret = 0; ++ ++ if (dev != DEVICE_MINOR) ++ ret = -ENXIO; ++ ++ return ret; ++} ++ ++static const struct vm_operations_struct rpi_gpiomem_vm_ops = { ++#ifdef CONFIG_HAVE_IOREMAP_PROT ++ .access = generic_access_phys ++#endif ++}; ++ ++static int rpi_gpiomem_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int i; ++ struct rpi_gpiomem_priv *priv; ++ unsigned long base; ++ unsigned long len = 0; ++ unsigned long offset; ++ ++ priv = file->private_data; ++ /* ++ * Userspace must provide a virtual address space at least ++ * the size of the concatenated ranges. ++ */ ++ for (i = 0; i < priv->nr_wins; i++) ++ len += priv->iowins[i].len; ++ if (len > vma->vm_end - vma->vm_start + 1) ++ return -EINVAL; ++ ++ vma->vm_ops = &rpi_gpiomem_vm_ops; ++ offset = vma->vm_start; ++ for (i = 0; i < priv->nr_wins; i++) { ++ base = priv->iowins[i].phys_base >> PAGE_SHIFT; ++ len = priv->iowins[i].len; ++ vma->vm_page_prot = phys_mem_access_prot(file, base, len, ++ vma->vm_page_prot); ++ if (remap_pfn_range(vma, offset, ++ base, len, ++ vma->vm_page_prot)) ++ break; ++ offset += len; ++ } ++ ++ if (i < priv->nr_wins) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++static const struct file_operations rpi_gpiomem_fops = { ++ .owner = THIS_MODULE, ++ .open = rpi_gpiomem_open, ++ .release = rpi_gpiomem_release, ++ .mmap = rpi_gpiomem_mmap, ++}; ++ ++static const struct of_device_id rpi_gpiomem_of_match[]; ++ ++static int rpi_gpiomem_probe(struct platform_device *pdev) ++{ ++ int err, i; ++ const struct of_device_id *id; ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct resource *ioresource; ++ struct rpi_gpiomem_priv *priv; ++ ++ /* Allocate buffers and instance data */ ++ ++ priv = kzalloc(sizeof(struct rpi_gpiomem_priv), GFP_KERNEL); ++ ++ if (!priv) { ++ err = -ENOMEM; ++ goto failed_inst_alloc; ++ } ++ platform_set_drvdata(pdev, priv); ++ ++ priv->dev = dev; ++ id = of_match_device(rpi_gpiomem_of_match, dev); ++ if (!id) ++ return -EINVAL; ++ ++ /* ++ * Device node naming - for legacy (bcm2835) DT bindings, the driver ++ * created the node based on a hardcoded name - for new bindings, ++ * take the node name from DT. ++ */ ++ if (id == &rpi_gpiomem_of_match[0]) { ++ priv->name = "gpiomem"; ++ } else { ++ err = of_property_read_string(node, "chardev-name", &priv->name); ++ if (err) ++ return -EINVAL; ++ } ++ ++ /* ++ * Go find the register ranges associated with this instance ++ */ ++ for (i = 0; i < MAX_RANGES; i++) { ++ ioresource = platform_get_resource(pdev, IORESOURCE_MEM, i); ++ if (!ioresource && i == 0) { ++ dev_err(priv->dev, "failed to get IO resource - no ranges available\n"); ++ err = -ENOENT; ++ goto failed_get_resource; ++ } ++ if (!ioresource) ++ break; ++ ++ priv->iowins[i].phys_base = ioresource->start; ++ priv->iowins[i].len = (ioresource->end + 1) - ioresource->start; ++ dev_info(&pdev->dev, "window base 0x%08lx size 0x%08lx\n", ++ priv->iowins[i].phys_base, priv->iowins[i].len); ++ priv->nr_wins++; ++ } ++ ++ /* Create character device entries */ ++ ++ err = alloc_chrdev_region(&priv->devid, ++ DEVICE_MINOR, 1, priv->name); ++ if (err != 0) { ++ dev_err(priv->dev, "unable to allocate device number"); ++ goto failed_alloc_chrdev; ++ } ++ cdev_init(&priv->rpi_gpiomem_cdev, &rpi_gpiomem_fops); ++ priv->rpi_gpiomem_cdev.owner = THIS_MODULE; ++ err = cdev_add(&priv->rpi_gpiomem_cdev, priv->devid, 1); ++ if (err != 0) { ++ dev_err(priv->dev, "unable to register device"); ++ goto failed_cdev_add; ++ } ++ ++ /* Create sysfs entries */ ++ ++ priv->class = class_create(THIS_MODULE, priv->name); ++ if (IS_ERR(priv->class)) { ++ err = PTR_ERR(priv->class); ++ goto failed_class_create; ++ } ++ ++ dev = device_create(priv->class, NULL, priv->devid, NULL, priv->name); ++ if (IS_ERR(dev)) { ++ err = PTR_ERR(dev); ++ goto failed_device_create; ++ } ++ ++ dev_info(priv->dev, "initialised %u regions as /dev/%s\n", ++ priv->nr_wins, priv->name); ++ ++ return 0; ++ ++failed_device_create: ++ class_destroy(priv->class); ++failed_class_create: ++ cdev_del(&priv->rpi_gpiomem_cdev); ++failed_cdev_add: ++ unregister_chrdev_region(priv->devid, 1); ++failed_alloc_chrdev: ++failed_get_resource: ++ kfree(priv); ++failed_inst_alloc: ++ dev_err(&pdev->dev, "could not load rpi_gpiomem"); ++ return err; ++} ++ ++static int rpi_gpiomem_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rpi_gpiomem_priv *priv = platform_get_drvdata(pdev); ++ ++ device_destroy(priv->class, priv->devid); ++ class_destroy(priv->class); ++ cdev_del(&priv->rpi_gpiomem_cdev); ++ unregister_chrdev_region(priv->devid, 1); ++ kfree(priv); ++ ++ dev_info(dev, "%s driver removed - OK", priv->name); ++ return 0; ++} ++ ++static const struct of_device_id rpi_gpiomem_of_match[] = { ++ { ++ .compatible = "brcm,bcm2835-gpiomem", ++ }, ++ { ++ .compatible = "raspberrypi,gpiomem", ++ }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rpi_gpiomem_of_match); ++ ++static struct platform_driver rpi_gpiomem_driver = { ++ .probe = rpi_gpiomem_probe, ++ .remove = rpi_gpiomem_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rpi_gpiomem_of_match, ++ }, ++}; ++ ++module_platform_driver(rpi_gpiomem_driver); ++ ++MODULE_ALIAS("platform:rpi-gpiomem"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("Driver for accessing GPIOs from userspace"); ++MODULE_AUTHOR("Jonathan Bell "); diff --git a/target/linux/bcm27xx/patches-6.1/950-0909-drivers-char-delete-bcm2835-gpiomem.patch b/target/linux/bcm27xx/patches-6.1/950-0909-drivers-char-delete-bcm2835-gpiomem.patch new file mode 100644 index 0000000000..5d6eb16fb2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0909-drivers-char-delete-bcm2835-gpiomem.patch @@ -0,0 +1,301 @@ +From 27bda80061b46e18fe83be11228df5365363b377 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 26 Apr 2023 13:44:15 +0100 +Subject: [PATCH] drivers: char: delete bcm2835-gpiomem + +This functionality is now provided by raspberrypi-gpiomem. + +Signed-off-by: Jonathan Bell +--- + drivers/char/broadcom/Kconfig | 8 - + drivers/char/broadcom/Makefile | 1 - + drivers/char/broadcom/bcm2835-gpiomem.c | 258 ------------------------ + 3 files changed, 267 deletions(-) + delete mode 100644 drivers/char/broadcom/bcm2835-gpiomem.c + +--- a/drivers/char/broadcom/Kconfig ++++ b/drivers/char/broadcom/Kconfig +@@ -23,14 +23,6 @@ config BCM_VCIO + + endif + +-config BCM2835_DEVGPIOMEM +- tristate "/dev/gpiomem rootless GPIO access via mmap() on the BCM2835" +- default m +- help +- Provides users with root-free access to the GPIO registers +- on the 2835. Calling mmap(/dev/gpiomem) will map the GPIO +- register page to the user's pointer. +- + config BCM2835_SMI_DEV + tristate "Character device driver for BCM2835 Secondary Memory Interface" + depends on BCM2835_SMI +--- a/drivers/char/broadcom/Makefile ++++ b/drivers/char/broadcom/Makefile +@@ -1,5 +1,4 @@ + obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o + obj-$(CONFIG_BCM_VCIO) += vcio.o +-obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o + obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o + obj-$(CONFIG_RPIVID_MEM) += rpivid-mem.o +--- a/drivers/char/broadcom/bcm2835-gpiomem.c ++++ /dev/null +@@ -1,258 +0,0 @@ +-/** +- * GPIO memory device driver +- * +- * Creates a chardev /dev/gpiomem which will provide user access to +- * the BCM2835's GPIO registers when it is mmap()'d. +- * No longer need root for user GPIO access, but without relaxing permissions +- * on /dev/mem. +- * +- * Written by Luke Wren +- * Copyright (c) 2015, Raspberry Pi (Trading) Ltd. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions, and the following disclaimer, +- * without modification. +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * 3. The names of the above-listed copyright holders may not be used +- * to endorse or promote products derived from this software without +- * specific prior written permission. +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") version 2, as published by the Free +- * Software Foundation. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define DEVICE_NAME "bcm2835-gpiomem" +-#define DRIVER_NAME "gpiomem-bcm2835" +-#define DEVICE_MINOR 0 +- +-struct bcm2835_gpiomem_instance { +- unsigned long gpio_regs_phys; +- struct device *dev; +-}; +- +-static struct cdev bcm2835_gpiomem_cdev; +-static dev_t bcm2835_gpiomem_devid; +-static struct class *bcm2835_gpiomem_class; +-static struct device *bcm2835_gpiomem_dev; +-static struct bcm2835_gpiomem_instance *inst; +- +- +-/**************************************************************************** +-* +-* GPIO mem chardev file ops +-* +-***************************************************************************/ +- +-static int bcm2835_gpiomem_open(struct inode *inode, struct file *file) +-{ +- int dev = iminor(inode); +- int ret = 0; +- +- if (dev != DEVICE_MINOR) { +- dev_err(inst->dev, "Unknown minor device: %d", dev); +- ret = -ENXIO; +- } +- return ret; +-} +- +-static int bcm2835_gpiomem_release(struct inode *inode, struct file *file) +-{ +- int dev = iminor(inode); +- int ret = 0; +- +- if (dev != DEVICE_MINOR) { +- dev_err(inst->dev, "Unknown minor device %d", dev); +- ret = -ENXIO; +- } +- return ret; +-} +- +-static const struct vm_operations_struct bcm2835_gpiomem_vm_ops = { +-#ifdef CONFIG_HAVE_IOREMAP_PROT +- .access = generic_access_phys +-#endif +-}; +- +-static int bcm2835_gpiomem_mmap(struct file *file, struct vm_area_struct *vma) +-{ +- /* Ignore what the user says - they're getting the GPIO regs +- whether they like it or not! */ +- unsigned long gpio_page = inst->gpio_regs_phys >> PAGE_SHIFT; +- +- vma->vm_page_prot = phys_mem_access_prot(file, gpio_page, +- PAGE_SIZE, +- vma->vm_page_prot); +- vma->vm_ops = &bcm2835_gpiomem_vm_ops; +- if (remap_pfn_range(vma, vma->vm_start, +- gpio_page, +- PAGE_SIZE, +- vma->vm_page_prot)) { +- return -EAGAIN; +- } +- return 0; +-} +- +-static const struct file_operations +-bcm2835_gpiomem_fops = { +- .owner = THIS_MODULE, +- .open = bcm2835_gpiomem_open, +- .release = bcm2835_gpiomem_release, +- .mmap = bcm2835_gpiomem_mmap, +-}; +- +- +- /**************************************************************************** +-* +-* Probe and remove functions +-* +-***************************************************************************/ +- +- +-static int bcm2835_gpiomem_probe(struct platform_device *pdev) +-{ +- int err; +- void *ptr_err; +- struct device *dev = &pdev->dev; +- struct resource *ioresource; +- +- /* Allocate buffers and instance data */ +- +- inst = kzalloc(sizeof(struct bcm2835_gpiomem_instance), GFP_KERNEL); +- +- if (!inst) { +- err = -ENOMEM; +- goto failed_inst_alloc; +- } +- +- inst->dev = dev; +- +- ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (ioresource) { +- inst->gpio_regs_phys = ioresource->start; +- } else { +- dev_err(inst->dev, "failed to get IO resource"); +- err = -ENOENT; +- goto failed_get_resource; +- } +- +- /* Create character device entries */ +- +- err = alloc_chrdev_region(&bcm2835_gpiomem_devid, +- DEVICE_MINOR, 1, DEVICE_NAME); +- if (err != 0) { +- dev_err(inst->dev, "unable to allocate device number"); +- goto failed_alloc_chrdev; +- } +- cdev_init(&bcm2835_gpiomem_cdev, &bcm2835_gpiomem_fops); +- bcm2835_gpiomem_cdev.owner = THIS_MODULE; +- err = cdev_add(&bcm2835_gpiomem_cdev, bcm2835_gpiomem_devid, 1); +- if (err != 0) { +- dev_err(inst->dev, "unable to register device"); +- goto failed_cdev_add; +- } +- +- /* Create sysfs entries */ +- +- bcm2835_gpiomem_class = class_create(THIS_MODULE, DEVICE_NAME); +- ptr_err = bcm2835_gpiomem_class; +- if (IS_ERR(ptr_err)) +- goto failed_class_create; +- +- bcm2835_gpiomem_dev = device_create(bcm2835_gpiomem_class, NULL, +- bcm2835_gpiomem_devid, NULL, +- "gpiomem"); +- ptr_err = bcm2835_gpiomem_dev; +- if (IS_ERR(ptr_err)) +- goto failed_device_create; +- +- dev_info(inst->dev, "Initialised: Registers at 0x%08lx", +- inst->gpio_regs_phys); +- +- return 0; +- +-failed_device_create: +- class_destroy(bcm2835_gpiomem_class); +-failed_class_create: +- cdev_del(&bcm2835_gpiomem_cdev); +- err = PTR_ERR(ptr_err); +-failed_cdev_add: +- unregister_chrdev_region(bcm2835_gpiomem_devid, 1); +-failed_alloc_chrdev: +-failed_get_resource: +- kfree(inst); +-failed_inst_alloc: +- dev_err(inst->dev, "could not load bcm2835_gpiomem"); +- return err; +-} +- +-static int bcm2835_gpiomem_remove(struct platform_device *pdev) +-{ +- struct device *dev = inst->dev; +- +- kfree(inst); +- device_destroy(bcm2835_gpiomem_class, bcm2835_gpiomem_devid); +- class_destroy(bcm2835_gpiomem_class); +- cdev_del(&bcm2835_gpiomem_cdev); +- unregister_chrdev_region(bcm2835_gpiomem_devid, 1); +- +- dev_info(dev, "GPIO mem driver removed - OK"); +- return 0; +-} +- +- /**************************************************************************** +-* +-* Register the driver with device tree +-* +-***************************************************************************/ +- +-static const struct of_device_id bcm2835_gpiomem_of_match[] = { +- {.compatible = "brcm,bcm2835-gpiomem",}, +- { /* sentinel */ }, +-}; +- +-MODULE_DEVICE_TABLE(of, bcm2835_gpiomem_of_match); +- +-static struct platform_driver bcm2835_gpiomem_driver = { +- .probe = bcm2835_gpiomem_probe, +- .remove = bcm2835_gpiomem_remove, +- .driver = { +- .name = DRIVER_NAME, +- .owner = THIS_MODULE, +- .of_match_table = bcm2835_gpiomem_of_match, +- }, +-}; +- +-module_platform_driver(bcm2835_gpiomem_driver); +- +-MODULE_ALIAS("platform:gpiomem-bcm2835"); +-MODULE_LICENSE("GPL"); +-MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +-MODULE_AUTHOR("Luke Wren "); diff --git a/target/linux/bcm27xx/patches-6.1/950-0910-drivers-hwmon-rp1-adc-check-conversion-validity-befo.patch b/target/linux/bcm27xx/patches-6.1/950-0910-drivers-hwmon-rp1-adc-check-conversion-validity-befo.patch new file mode 100644 index 0000000000..557b7ac406 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0910-drivers-hwmon-rp1-adc-check-conversion-validity-befo.patch @@ -0,0 +1,34 @@ +From 3cafcfbab9b5f3f1357b415b6ca09911eeb405d6 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Thu, 4 May 2023 15:48:53 +0100 +Subject: [PATCH] drivers: hwmon: rp1-adc: check conversion validity before + supplying value + +The SAR ADC architecture may complete a conversion but instability in the +comparator can corrupt the result. Such corruption is signalled in the CS +ERR bit, asserted alongside each conversion result. + +Signed-off-by: Jonathan Bell +--- + drivers/hwmon/rp1-adc.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/rp1-adc.c ++++ b/drivers/hwmon/rp1-adc.c +@@ -97,8 +97,14 @@ static int rp1_adc_read(struct rp1_adc_d + data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS); + + ret = rp1_adc_ready_wait(data); +- if (!ret) +- *val = readl(data->base + RP1_ADC_RESULT); ++ if (ret) ++ return ret; ++ ++ /* Asserted if the completed conversion had a convergence error */ ++ if (readl(data->base + RP1_ADC_CS) & RP1_ADC_CS_ERR) ++ return -EIO; ++ ++ *val = readl(data->base + RP1_ADC_RESULT); + + spin_unlock(&data->lock); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0911-dmaengine-bcm2835-Add-BCM2712-support.patch b/target/linux/bcm27xx/patches-6.1/950-0911-dmaengine-bcm2835-Add-BCM2712-support.patch new file mode 100644 index 0000000000..58095cf8fd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0911-dmaengine-bcm2835-Add-BCM2712-support.patch @@ -0,0 +1,36 @@ +From 87c5545f9a66984894384da5f8c2eeb60983732a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 8 Mar 2023 16:53:38 +0000 +Subject: [PATCH] dmaengine: bcm2835: Add BCM2712 support + +BCM2712 has 6 40-bit channels - DMA6 to DMA11. Add a new compatible +string to indicate that the current platform is BCM2712. + +Signed-off-by: Phil Elwell +--- + drivers/dma/bcm2835-dma.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -331,6 +331,12 @@ static const struct bcm2835_dma_cfg_data + .dma_mask = DMA_BIT_MASK(36), + }; + ++static const struct bcm2835_dma_cfg_data bcm2712_dma_cfg = { ++ .chan_40bit_mask = BIT(6) | BIT(7) | BIT(8) | BIT(9) | ++ BIT(10) | BIT(11), ++ .dma_mask = DMA_BIT_MASK(40), ++}; ++ + static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c) + { + /* lite and normal channels have different max frame length */ +@@ -1260,6 +1266,7 @@ EXPORT_SYMBOL(bcm2711_dma40_memcpy); + static const struct of_device_id bcm2835_dma_of_match[] = { + { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_cfg }, + { .compatible = "brcm,bcm2711-dma", .data = &bcm2711_dma_cfg }, ++ { .compatible = "brcm,bcm2712-dma", .data = &bcm2712_dma_cfg }, + {}, + }; + MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match); diff --git a/target/linux/bcm27xx/patches-6.1/950-0912-dmaengine-bcm2835-HACK-Support-DMA-Lite-channels.patch b/target/linux/bcm27xx/patches-6.1/950-0912-dmaengine-bcm2835-HACK-Support-DMA-Lite-channels.patch new file mode 100644 index 0000000000..6f651a65f6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0912-dmaengine-bcm2835-HACK-Support-DMA-Lite-channels.patch @@ -0,0 +1,57 @@ +From a671a2774cb3bcfb144622149757f6821aa0604c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 13 Apr 2023 16:52:19 +0200 +Subject: [PATCH] dmaengine: bcm2835: HACK: Support DMA-Lite channels + +The BCM2712 has a DMA-Lite controller that is basically a BCM2835-style +DMA controller that supports 40 bits DMA addresses. + +We need it for HDMI audio to work, but this breaks BCM2835-38 so we +should rework this later. + +Signed-off-by: Maxime Ripard +--- + drivers/dma/bcm2835-dma.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -550,7 +550,7 @@ static struct bcm2835_desc *bcm2835_dma_ + control_block->info = info; + control_block->src = src; + control_block->dst = dst; +- control_block->stride = 0; ++ control_block->stride = (upper_32_bits(dst) << 8) | upper_32_bits(src); + control_block->next = 0; + } + +@@ -575,7 +575,7 @@ static struct bcm2835_desc *bcm2835_dma_ + d->cb_list[frame - 1].cb)->next_cb = + to_bcm2711_cbaddr(cb_entry->paddr); + if (frame && !c->is_40bit_channel) +- d->cb_list[frame - 1].cb->next = cb_entry->paddr; ++ d->cb_list[frame - 1].cb->next = to_bcm2711_cbaddr(cb_entry->paddr); + + /* update src and dst and length */ + if (src && (info & BCM2835_DMA_S_INC)) { +@@ -760,7 +760,10 @@ static void bcm2835_dma_start_desc(struc + writel(BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT | BCM2711_DMA40_CS_FLAGS(c->dreq), + c->chan_base + BCM2711_DMA40_CS); + } else { +- writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR); ++ writel(BIT(31), c->chan_base + BCM2835_DMA_CS); ++ ++ writel(to_bcm2711_cbaddr(d->cb_list[0].paddr), ++ c->chan_base + BCM2835_DMA_ADDR); + writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq), + c->chan_base + BCM2835_DMA_CS); + } +@@ -1129,7 +1132,7 @@ static struct dma_async_tx_descriptor *b + d->cb_list[frames - 1].cb)->next_cb = + to_bcm2711_cbaddr(d->cb_list[0].paddr); + else +- d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr; ++ d->cb_list[d->frames - 1].cb->next = to_bcm2711_cbaddr(d->cb_list[0].paddr); + + return vchan_tx_prep(&c->vc, &d->vd, flags); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0913-clk-bcm-rpi-Add-disp-clock.patch b/target/linux/bcm27xx/patches-6.1/950-0913-clk-bcm-rpi-Add-disp-clock.patch new file mode 100644 index 0000000000..6f5e55d956 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0913-clk-bcm-rpi-Add-disp-clock.patch @@ -0,0 +1,46 @@ +From c8fd69c6f567bd43ba084b95a987532940465ef5 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Feb 2023 14:12:50 +0100 +Subject: [PATCH] clk: bcm: rpi: Add disp clock + +BCM2712 has an extra clock exposed by the firmware called DISP, and used +by (at least) the HVS. Let's add it to the list of clocks to register in +Linux. + +Signed-off-by: Maxime Ripard +--- + drivers/clk/bcm/clk-raspberrypi.c | 5 +++++ + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 2 files changed, 6 insertions(+) + +--- a/drivers/clk/bcm/clk-raspberrypi.c ++++ b/drivers/clk/bcm/clk-raspberrypi.c +@@ -34,6 +34,7 @@ static char *rpi_firmware_clk_names[] = + [RPI_FIRMWARE_M2MC_CLK_ID] = "m2mc", + [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb", + [RPI_FIRMWARE_VEC_CLK_ID] = "vec", ++ [RPI_FIRMWARE_DISP_CLK_ID] = "disp", + }; + + #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0) +@@ -139,6 +140,10 @@ raspberrypi_clk_variants[RPI_FIRMWARE_NU + .export = true, + .minimize = true, + }, ++ [RPI_FIRMWARE_DISP_CLK_ID] = { ++ .export = true, ++ .minimize = true, ++ }, + }; + + /* +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -176,6 +176,7 @@ enum rpi_firmware_clk_id { + RPI_FIRMWARE_M2MC_CLK_ID, + RPI_FIRMWARE_PIXEL_BVB_CLK_ID, + RPI_FIRMWARE_VEC_CLK_ID, ++ RPI_FIRMWARE_DISP_CLK_ID, + RPI_FIRMWARE_NUM_CLK_ID, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0914-net-phy-broadcom-optionally-enable-link-down-powersa.patch b/target/linux/bcm27xx/patches-6.1/950-0914-net-phy-broadcom-optionally-enable-link-down-powersa.patch new file mode 100644 index 0000000000..2df48297b5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0914-net-phy-broadcom-optionally-enable-link-down-powersa.patch @@ -0,0 +1,26 @@ +From 6370a6cd16a5aa9726bf209c0f0a3179f4011cb1 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 22 May 2023 15:31:17 +0100 +Subject: [PATCH] net: phy: broadcom: optionally enable link-down powersave + based on DT + +It's really a function of the board whether or not to use this feature +as it may require MAC compatibility as well as interop testing. + +Signed-off-by: Jonathan Bell +--- + drivers/net/phy/broadcom.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -370,6 +370,9 @@ static int bcm54xx_config_init(struct ph + (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) + bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); + ++ if (of_property_read_bool(np, "brcm,powerdown-enable")) ++ phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; ++ + bcm54xx_adjust_rxrefclk(phydev); + + switch (BRCM_PHY_MODEL(phydev)) { diff --git a/target/linux/bcm27xx/patches-6.1/950-0915-dmaengine-bcm2835-Rename-to_bcm2711_cbaddr-to-to_40b.patch b/target/linux/bcm27xx/patches-6.1/950-0915-dmaengine-bcm2835-Rename-to_bcm2711_cbaddr-to-to_40b.patch new file mode 100644 index 0000000000..ce59f6072b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0915-dmaengine-bcm2835-Rename-to_bcm2711_cbaddr-to-to_40b.patch @@ -0,0 +1,75 @@ +From cfad3f71fc450639fc259d576d0903e9132fe34a Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Thu, 25 May 2023 14:48:28 +0100 +Subject: [PATCH] dmaengine: bcm2835: Rename to_bcm2711_cbaddr to + to_40bit_cbaddr + +As the shifted address also applies to bcm2712, +give the function a more specific name. + +Signed-off-by: Dom Cobley +--- + drivers/dma/bcm2835-dma.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -390,7 +390,7 @@ static inline uint32_t to_bcm2711_dsti(u + BCM2711_DMA40_BURST_LEN(BCM2835_DMA_GET_BURST_LENGTH(info)); + } + +-static inline uint32_t to_bcm2711_cbaddr(dma_addr_t addr) ++static inline uint32_t to_40bit_cbaddr(dma_addr_t addr) + { + BUG_ON(addr & 0x1f); + return (addr >> 5); +@@ -573,9 +573,9 @@ static struct bcm2835_desc *bcm2835_dma_ + if (frame && c->is_40bit_channel) + ((struct bcm2711_dma40_scb *) + d->cb_list[frame - 1].cb)->next_cb = +- to_bcm2711_cbaddr(cb_entry->paddr); ++ to_40bit_cbaddr(cb_entry->paddr); + if (frame && !c->is_40bit_channel) +- d->cb_list[frame - 1].cb->next = to_bcm2711_cbaddr(cb_entry->paddr); ++ d->cb_list[frame - 1].cb->next = to_40bit_cbaddr(cb_entry->paddr); + + /* update src and dst and length */ + if (src && (info & BCM2835_DMA_S_INC)) { +@@ -755,14 +755,14 @@ static void bcm2835_dma_start_desc(struc + c->desc = d = to_bcm2835_dma_desc(&vd->tx); + + if (c->is_40bit_channel) { +- writel(to_bcm2711_cbaddr(d->cb_list[0].paddr), ++ writel(to_40bit_cbaddr(d->cb_list[0].paddr), + c->chan_base + BCM2711_DMA40_CB); + writel(BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT | BCM2711_DMA40_CS_FLAGS(c->dreq), + c->chan_base + BCM2711_DMA40_CS); + } else { + writel(BIT(31), c->chan_base + BCM2835_DMA_CS); + +- writel(to_bcm2711_cbaddr(d->cb_list[0].paddr), ++ writel(to_40bit_cbaddr(d->cb_list[0].paddr), + c->chan_base + BCM2835_DMA_ADDR); + writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq), + c->chan_base + BCM2835_DMA_CS); +@@ -1130,9 +1130,9 @@ static struct dma_async_tx_descriptor *b + if (c->is_40bit_channel) + ((struct bcm2711_dma40_scb *) + d->cb_list[frames - 1].cb)->next_cb = +- to_bcm2711_cbaddr(d->cb_list[0].paddr); ++ to_40bit_cbaddr(d->cb_list[0].paddr); + else +- d->cb_list[d->frames - 1].cb->next = to_bcm2711_cbaddr(d->cb_list[0].paddr); ++ d->cb_list[d->frames - 1].cb->next = to_40bit_cbaddr(d->cb_list[0].paddr); + + return vchan_tx_prep(&c->vc, &d->vd, flags); + } +@@ -1252,7 +1252,7 @@ void bcm2711_dma40_memcpy(dma_addr_t dst + scb->len = size; + scb->next_cb = 0; + +- writel(to_bcm2711_cbaddr(memcpy_scb_dma), memcpy_chan + BCM2711_DMA40_CB); ++ writel(to_40bit_cbaddr(memcpy_scb_dma), memcpy_chan + BCM2711_DMA40_CB); + writel(BCM2711_DMA40_MEMCPY_FLAGS | BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT, + memcpy_chan + BCM2711_DMA40_CS); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0916-dmaengine-bcm2835-Fix-dma-driver-for-BCM2835-38.patch b/target/linux/bcm27xx/patches-6.1/950-0916-dmaengine-bcm2835-Fix-dma-driver-for-BCM2835-38.patch new file mode 100644 index 0000000000..a2ff2a6bb0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0916-dmaengine-bcm2835-Fix-dma-driver-for-BCM2835-38.patch @@ -0,0 +1,77 @@ +From 75f44d1416c5de17865247d6d012c37f7650437c Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 24 May 2023 19:32:16 +0100 +Subject: [PATCH] dmaengine: bcm2835: Fix dma driver for BCM2835-38 + +The previous commit broke support on older devices. +Make the breaking parts of patch conditional on +the device being used. + +Fixes: 6e1856ac7c39 ("dmaengine: bcm2835: HACK: Support DMA-Lite channels") + +Signed-off-by: Dom Cobley +--- + drivers/dma/bcm2835-dma.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -102,6 +102,7 @@ struct bcm2835_chan { + + bool is_lite_channel; + bool is_40bit_channel; ++ bool is_2712; + }; + + struct bcm2835_desc { +@@ -550,7 +551,11 @@ static struct bcm2835_desc *bcm2835_dma_ + control_block->info = info; + control_block->src = src; + control_block->dst = dst; +- control_block->stride = (upper_32_bits(dst) << 8) | upper_32_bits(src); ++ if (c->is_2712) ++ control_block->stride = (upper_32_bits(dst) << 8) | ++ upper_32_bits(src); ++ else ++ control_block->stride = 0; + control_block->next = 0; + } + +@@ -575,7 +580,8 @@ static struct bcm2835_desc *bcm2835_dma_ + d->cb_list[frame - 1].cb)->next_cb = + to_40bit_cbaddr(cb_entry->paddr); + if (frame && !c->is_40bit_channel) +- d->cb_list[frame - 1].cb->next = to_40bit_cbaddr(cb_entry->paddr); ++ d->cb_list[frame - 1].cb->next = c->is_2712 ? ++ to_40bit_cbaddr(cb_entry->paddr) : cb_entry->paddr; + + /* update src and dst and length */ + if (src && (info & BCM2835_DMA_S_INC)) { +@@ -762,7 +768,7 @@ static void bcm2835_dma_start_desc(struc + } else { + writel(BIT(31), c->chan_base + BCM2835_DMA_CS); + +- writel(to_40bit_cbaddr(d->cb_list[0].paddr), ++ writel(c->is_2712 ? to_40bit_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr, + c->chan_base + BCM2835_DMA_ADDR); + writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq), + c->chan_base + BCM2835_DMA_CS); +@@ -1132,7 +1138,8 @@ static struct dma_async_tx_descriptor *b + d->cb_list[frames - 1].cb)->next_cb = + to_40bit_cbaddr(d->cb_list[0].paddr); + else +- d->cb_list[d->frames - 1].cb->next = to_40bit_cbaddr(d->cb_list[0].paddr); ++ d->cb_list[d->frames - 1].cb->next = c->is_2712 ? ++ to_40bit_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr; + + return vchan_tx_prep(&c->vc, &d->vd, flags); + } +@@ -1199,6 +1206,8 @@ static int bcm2835_dma_chan_init(struct + else if (readl(c->chan_base + BCM2835_DMA_DEBUG) & + BCM2835_DMA_DEBUG_LITE) + c->is_lite_channel = true; ++ if (d->cfg_data->dma_mask == DMA_BIT_MASK(40)) ++ c->is_2712 = true; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0917-drivers-iommu-Add-BCM2712-IOMMU.patch b/target/linux/bcm27xx/patches-6.1/950-0917-drivers-iommu-Add-BCM2712-IOMMU.patch new file mode 100644 index 0000000000..92f43fa71b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0917-drivers-iommu-Add-BCM2712-IOMMU.patch @@ -0,0 +1,855 @@ +From 5fd6ee7fd084838e09d4e463ae53cd9aaa7fce70 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Thu, 11 May 2023 16:37:34 +0100 +Subject: [PATCH] drivers: iommu: Add BCM2712 IOMMU + +Add a driver for BCM2712 IOMMUs. +There is a small driver for the Shared IOMMU TLB Cache. +Each IOMMU instance is a separate device. + +IOMMUs are set up with a "pass-through" range covering +the lowest 40BGytes (which should cover all of SDRAM) +for the benefit of non-IOMMU-aware devices that share +a physical IOMMU; and translation for addresses in the +range 40GB to 42GB. + +An optional parameter adds a DMA offset (which otherwise +would be lost?) to virtual addresses for DMA masters on a +bus such as PCIe. + +Signed-off-by: Nick Hollinghurst +--- + drivers/iommu/Kconfig | 7 + + drivers/iommu/Makefile | 1 + + drivers/iommu/bcm2712-iommu-cache.c | 77 ++++ + drivers/iommu/bcm2712-iommu.c | 672 ++++++++++++++++++++++++++++ + drivers/iommu/bcm2712-iommu.h | 45 ++ + 5 files changed, 802 insertions(+) + create mode 100644 drivers/iommu/bcm2712-iommu-cache.c + create mode 100644 drivers/iommu/bcm2712-iommu.c + create mode 100644 drivers/iommu/bcm2712-iommu.h + +--- a/drivers/iommu/Kconfig ++++ b/drivers/iommu/Kconfig +@@ -506,4 +506,11 @@ config SPRD_IOMMU + + Say Y here if you want to use the multimedia devices listed above. + ++config BCM2712_IOMMU ++ tristate "BCM2712 IOMMU driver" ++ depends on ARM64 && ARCH_BCM ++ select IOMMU_API ++ help ++ IOMMU driver for BCM2712 ++ + endif # IOMMU_SUPPORT +--- a/drivers/iommu/Makefile ++++ b/drivers/iommu/Makefile +@@ -31,3 +31,4 @@ obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iom + obj-$(CONFIG_IOMMU_SVA) += iommu-sva-lib.o io-pgfault.o + obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o + obj-$(CONFIG_APPLE_DART) += apple-dart.o ++obj-$(CONFIG_BCM2712_IOMMU) += bcm2712-iommu.o bcm2712-iommu-cache.o +--- /dev/null ++++ b/drivers/iommu/bcm2712-iommu-cache.c +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * IOMMU driver for BCM2712 ++ * ++ * Copyright (c) 2023 Raspberry Pi Ltd. ++ */ ++ ++#include "bcm2712-iommu.h" ++ ++#include ++#include ++#include ++#include ++ ++#define MMUC_CONTROL_ENABLE 1 ++#define MMUC_CONTROL_FLUSH 2 ++#define MMUC_CONTROL_FLUSHING 4 ++ ++void bcm2712_iommu_cache_flush(struct bcm2712_iommu_cache *cache) ++{ ++ unsigned long flags; ++ int i; ++ ++ spin_lock_irqsave(&cache->hw_lock, flags); ++ if (cache->reg_base) { ++ /* Enable and flush the TLB cache */ ++ writel(MMUC_CONTROL_ENABLE | MMUC_CONTROL_FLUSH, ++ cache->reg_base); ++ ++ /* Wait for flush to complete: it should be very quick */ ++ for (i = 0; i < 1024; i++) { ++ if (!(MMUC_CONTROL_FLUSHING & readl(cache->reg_base))) ++ break; ++ cpu_relax(); ++ } ++ } ++ spin_unlock_irqrestore(&cache->hw_lock, flags); ++} ++ ++static int bcm2712_iommu_cache_probe(struct platform_device *pdev) ++{ ++ struct bcm2712_iommu_cache *cache; ++ ++ dev_info(&pdev->dev, __func__); ++ cache = devm_kzalloc(&pdev->dev, sizeof(*cache), GFP_KERNEL); ++ if (!cache) ++ return -ENOMEM; ++ ++ cache->dev = &pdev->dev; ++ platform_set_drvdata(pdev, cache); ++ spin_lock_init(&cache->hw_lock); ++ ++ /* Get IOMMUC registers; we only use the first register (IOMMUC_CTRL) */ ++ cache->reg_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(cache->reg_base)) { ++ dev_err(&pdev->dev, "Failed to get IOMMU Cache registers address\n"); ++ cache->reg_base = NULL; ++ } ++ return 0; ++} ++ ++static const struct of_device_id bcm2712_iommu_cache_of_match[] = { ++ { ++ . compatible = "brcm,bcm2712-iommuc" ++ }, ++ { /* sentinel */ }, ++}; ++ ++static struct platform_driver bcm2712_iommu_cache_driver = { ++ .probe = bcm2712_iommu_cache_probe, ++ .driver = { ++ .name = "bcm2712-iommu-cache", ++ .of_match_table = bcm2712_iommu_cache_of_match ++ }, ++}; ++ ++builtin_platform_driver(bcm2712_iommu_cache_driver); +--- /dev/null ++++ b/drivers/iommu/bcm2712-iommu.c +@@ -0,0 +1,672 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * IOMMU driver for BCM2712 ++ * ++ * Copyright (c) 2023 Raspberry Pi Ltd. ++ */ ++ ++#include "bcm2712-iommu.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MMU_WR(off, val) writel(val, mmu->reg_base + (off)) ++#define MMU_RD(off) readl(mmu->reg_base + (off)) ++ ++#define domain_to_mmu(d) (container_of(d, struct bcm2712_iommu_domain, base)->mmu) ++ ++#define MMMU_CTRL_OFFSET 0x00 ++#define MMMU_CTRL_CAP_EXCEEDED BIT(27) ++#define MMMU_CTRL_CAP_EXCEEDED_ABORT_EN BIT(26) ++#define MMMU_CTRL_CAP_EXCEEDED_INT_EN BIT(25) ++#define MMMU_CTRL_CAP_EXCEEDED_EXCEPTION_EN BIT(24) ++#define MMMU_CTRL_PT_INVALID BIT(20) ++#define MMMU_CTRL_PT_INVALID_ABORT_EN BIT(19) ++#define MMMU_CTRL_PT_INVALID_EXCEPTION_EN BIT(18) ++#define MMMU_CTRL_PT_INVALID_EN BIT(17) ++#define MMMU_CTRL_WRITE_VIOLATION BIT(12) ++#define MMMU_CTRL_WRITE_VIOLATION_ABORT_EN BIT(11) ++#define MMMU_CTRL_WRITE_VIOLATION_INT_EN BIT(10) ++#define MMMU_CTRL_WRITE_VIOLATION_EXCEPTION_EN BIT(9) ++#define MMMU_CTRL_BYPASS BIT(8) ++#define MMMU_CTRL_TLB_CLEARING BIT(7) ++#define MMMU_CTRL_STATS_CLEAR BIT(3) ++#define MMMU_CTRL_TLB_CLEAR BIT(2) ++#define MMMU_CTRL_STATS_ENABLE BIT(1) ++#define MMMU_CTRL_ENABLE BIT(0) ++ ++#define MMMU_PT_PA_BASE_OFFSET 0x04 ++ ++#define MMMU_HIT_OFFSET 0x08 ++#define MMMU_MISS_OFFSET 0x0C ++#define MMMU_STALL_OFFSET 0x10 ++ ++#define MMMU_ADDR_CAP_OFFSET 0x14 ++#define MMMU_ADDR_CAP_ENABLE BIT(31) ++#define ADDR_CAP_SHIFT 28 /* ADDR_CAP is defined to be in 256 MByte units */ ++ ++#define MMMU_SHOOT_DOWN_OFFSET 0x18 ++#define MMMU_SHOOT_DOWN_SHOOTING BIT(31) ++#define MMMU_SHOOT_DOWN_SHOOT BIT(30) ++ ++#define MMMU_BYPASS_START_OFFSET 0x1C ++#define MMMU_BYPASS_START_ENABLE BIT(31) ++#define MMMU_BYPASS_START_INVERT BIT(30) ++ ++#define MMMU_BYPASS_END_OFFSET 0x20 ++#define MMMU_BYPASS_END_ENABLE BIT(31) ++ ++#define MMMU_MISC_OFFSET 0x24 ++#define MMMU_MISC_SINGLE_TABLE BIT(31) ++ ++#define MMMU_ILLEGAL_ADR_OFFSET 0x30 ++#define MMMU_ILLEGAL_ADR_ENABLE BIT(31) ++ ++#define MMMU_DEBUG_INFO_OFFSET 0x38 ++#define MMMU_DEBUG_INFO_VERSION_MASK 0x0000000Fu ++#define MMMU_DEBUG_INFO_VA_WIDTH_MASK 0x000000F0u ++#define MMMU_DEBUG_INFO_PA_WIDTH_MASK 0x00000F00u ++#define MMMU_DEBUG_INFO_BIGPAGE_WIDTH_MASK 0x000FF000u ++#define MMMU_DEBUG_INFO_SUPERPAGE_WIDTH_MASK 0x0FF00000u ++#define MMMU_DEBUG_INFO_BYPASS_4M BIT(28) ++#define MMMU_DEBUG_INFO_BYPASS BIT(29) ++ ++#define MMMU_PTE_PAGESIZE_MASK 0xC0000000u ++#define MMMU_PTE_WRITEABLE BIT(29) ++#define MMMU_PTE_VALID BIT(28) ++ ++/* ++ * BCM2712 IOMMU is organized around 4Kbyte pages (MMU_PAGE_SIZE). ++ * Linux PAGE_SIZE must not be smaller but may be larger (e.g. 4K, 16K). ++ * ++ * Unlike many larger MMUs, this one uses a 4-byte word size, allowing ++ * 1024 entries within each 4K table page, and two-level translation. ++ * ++ * Let's allocate enough table space for 2GB of translated memory (IOVA). ++ * This requires 512 4K pages (2MB) of level-2 tables, one page of ++ * top-level table (only half-filled in this particular configuration), ++ * plus one "default" page to catch illegal requests. ++ * ++ * The translated virtual address region is between 40GB and 42GB; ++ * addresses below this range pass straight through to the SDRAM. ++ * ++ * Currently we assume a 1:1:1 correspondence of IOMMU, group and domain. ++ */ ++ ++#define MMU_PAGE_SHIFT 12 ++#define MMU_PAGE_SIZE BIT(MMU_PAGE_SHIFT) ++ ++#define PAGEWORDS_SHIFT (MMU_PAGE_SHIFT - 2) ++#define HUGEPAGE_SHIFT (MMU_PAGE_SHIFT + PAGEWORDS_SHIFT) ++#define L1_CHUNK_SHIFT (MMU_PAGE_SHIFT + 2 * PAGEWORDS_SHIFT) ++ ++#define APERTURE_BASE (40ul << 30) ++#define APERTURE_SIZE (2ul << 30) ++#define APERTURE_TOP (APERTURE_BASE + APERTURE_SIZE) ++#define TRANSLATED_PAGES (APERTURE_SIZE >> MMU_PAGE_SHIFT) ++#define L2_PAGES (TRANSLATED_PAGES >> PAGEWORDS_SHIFT) ++#define TABLES_ALLOC_SIZE (L2_PAGES * MMU_PAGE_SIZE + 2 * PAGE_SIZE) ++ ++static void bcm2712_iommu_init(struct bcm2712_iommu *mmu) ++{ ++ unsigned int i, bypass_shift; ++ struct sg_dma_page_iter it; ++ u32 u = MMU_RD(MMMU_DEBUG_INFO_OFFSET); ++ ++ /* ++ * Check IOMMU version and hardware configuration. ++ * This driver is for VC IOMMU version >= 4 (with 2-level tables) ++ * and assumes at least 36 bits of virtual and physical address space. ++ * Bigpage and superpage sizes are typically 64K and 1M, but may vary ++ * (hugepage size is fixed at 4M, the range covered by an L2 page). ++ */ ++ dev_info(mmu->dev, "%s: DEBUG_INFO = 0x%08x\n", __func__, u); ++ WARN_ON(FIELD_GET(MMMU_DEBUG_INFO_VERSION_MASK, u) < 4 || ++ FIELD_GET(MMMU_DEBUG_INFO_VA_WIDTH_MASK, u) < 6 || ++ FIELD_GET(MMMU_DEBUG_INFO_PA_WIDTH_MASK, u) < 6 || ++ !(u & MMMU_DEBUG_INFO_BYPASS)); ++ ++ mmu->bigpage_mask = ++ ((1u << FIELD_GET(MMMU_DEBUG_INFO_BIGPAGE_WIDTH_MASK, u)) - 1u) << MMU_PAGE_SHIFT; ++ mmu->superpage_mask = ++ ((1u << FIELD_GET(MMMU_DEBUG_INFO_SUPERPAGE_WIDTH_MASK, u)) - 1u) << MMU_PAGE_SHIFT; ++ bypass_shift = (u & MMMU_DEBUG_INFO_BYPASS_4M) ? ++ HUGEPAGE_SHIFT : ADDR_CAP_SHIFT; ++ ++ /* Disable MMU and clear sticky flags; meanwhile flush the TLB */ ++ MMU_WR(MMMU_CTRL_OFFSET, ++ MMMU_CTRL_CAP_EXCEEDED | ++ MMMU_CTRL_PT_INVALID | ++ MMMU_CTRL_WRITE_VIOLATION | ++ MMMU_CTRL_STATS_CLEAR | ++ MMMU_CTRL_TLB_CLEAR); ++ ++ /* ++ * Put MMU into 2-level mode; set address cap and "bypass" range ++ * (note that some of these registers have unintuitive off-by-ones). ++ * Addresses below APERTURE_BASE are passed unchanged: this is ++ * useful for blocks which share an IOMMU with other blocks ++ * whose drivers are not IOMMU-aware. ++ */ ++ MMU_WR(MMMU_MISC_OFFSET, ++ MMU_RD(MMMU_MISC_OFFSET) & ~MMMU_MISC_SINGLE_TABLE); ++ MMU_WR(MMMU_ADDR_CAP_OFFSET, ++ MMMU_ADDR_CAP_ENABLE + ++ (APERTURE_TOP >> ADDR_CAP_SHIFT) - 1); ++ if (APERTURE_BASE > 0) { ++ MMU_WR(MMMU_BYPASS_START_OFFSET, ++ MMMU_BYPASS_START_ENABLE + MMMU_BYPASS_START_INVERT + ++ (APERTURE_BASE >> bypass_shift) - 1); ++ MMU_WR(MMMU_BYPASS_END_OFFSET, ++ MMMU_BYPASS_END_ENABLE + ++ (APERTURE_TOP >> bypass_shift)); ++ } else { ++ MMU_WR(MMMU_BYPASS_START_OFFSET, 0); ++ MMU_WR(MMMU_BYPASS_END_OFFSET, 0); ++ } ++ ++ /* Ensure tables are zeroed (which marks all pages as invalid) */ ++ dma_sync_sgtable_for_cpu(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ memset(mmu->tables, 0, TABLES_ALLOC_SIZE); ++ mmu->nmapped_pages = 0; ++ ++ /* Initialize the high-level table to point to the low-level pages */ ++ __sg_page_iter_start(&it.base, mmu->sgt->sgl, mmu->sgt->nents, 0); ++ for (i = 0; i < L2_PAGES; i++) { ++ if (!(i % (PAGE_SIZE / MMU_PAGE_SIZE))) { ++ __sg_page_iter_dma_next(&it); ++ u = (sg_page_iter_dma_address(&it) >> MMU_PAGE_SHIFT); ++ } else { ++ u++; ++ } ++ mmu->tables[TRANSLATED_PAGES + i] = MMMU_PTE_VALID + u; ++ } ++ ++ /* ++ * Configure the addresses of the top-level table (offset because ++ * the aperture does not start from zero), and of the default page. ++ * For simplicity, both these regions are whole Linux pages. ++ */ ++ __sg_page_iter_dma_next(&it); ++ u = (sg_page_iter_dma_address(&it) >> MMU_PAGE_SHIFT); ++ MMU_WR(MMMU_PT_PA_BASE_OFFSET, u - (APERTURE_BASE >> L1_CHUNK_SHIFT)); ++ __sg_page_iter_dma_next(&it); ++ u = (sg_page_iter_dma_address(&it) >> MMU_PAGE_SHIFT); ++ MMU_WR(MMMU_ILLEGAL_ADR_OFFSET, MMMU_ILLEGAL_ADR_ENABLE + u); ++ dma_sync_sgtable_for_device(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = false; ++ ++ /* Flush (and enable) the shared TLB cache; enable this MMU. */ ++ if (mmu->cache) ++ bcm2712_iommu_cache_flush(mmu->cache); ++ MMU_WR(MMMU_CTRL_OFFSET, ++ MMMU_CTRL_CAP_EXCEEDED_ABORT_EN | ++ MMMU_CTRL_PT_INVALID_ABORT_EN | ++ MMMU_CTRL_WRITE_VIOLATION_ABORT_EN | ++ MMMU_CTRL_STATS_ENABLE | ++ MMMU_CTRL_ENABLE); ++} ++ ++static int bcm2712_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) ++{ ++ struct bcm2712_iommu *mmu = dev ? dev_iommu_priv_get(dev) : 0; ++ struct bcm2712_iommu_domain *mydomain = ++ container_of(domain, struct bcm2712_iommu_domain, base); ++ ++ dev_info(dev, "%s: MMU %s\n", ++ __func__, mmu ? dev_name(mmu->dev) : ""); ++ ++ if (mmu) { ++ mydomain->mmu = mmu; ++ mmu->domain = mydomain; ++ ++ if (mmu->dma_iova_offset) { ++ domain->geometry.aperture_start = ++ mmu->dma_iova_offset + APERTURE_BASE; ++ domain->geometry.aperture_end = ++ mmu->dma_iova_offset + APERTURE_TOP - 1ul; ++ } ++ ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++static void bcm2712_iommu_detach_dev(struct iommu_domain *domain, struct device *dev) ++{ ++ (void)domain; ++ (void)dev; ++} ++ ++static int bcm2712_iommu_map(struct iommu_domain *domain, unsigned long iova, ++ phys_addr_t pa, size_t bytes, int prot, gfp_t gfp) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ ++ (void)gfp; ++ iova -= mmu->dma_iova_offset; ++ if (iova >= APERTURE_BASE && iova + bytes <= APERTURE_TOP) { ++ unsigned int p; ++ u32 entry = MMMU_PTE_VALID | (pa >> MMU_PAGE_SHIFT); ++ u32 align = (u32)(iova | pa | bytes); ++ ++ /* large page and write enable flags */ ++ if (!(align & ((1 << HUGEPAGE_SHIFT) - 1))) ++ entry |= FIELD_PREP(MMMU_PTE_PAGESIZE_MASK, 3); ++ else if (!(align & mmu->superpage_mask) && mmu->superpage_mask) ++ entry |= FIELD_PREP(MMMU_PTE_PAGESIZE_MASK, 2); ++ else if (!(align & mmu->bigpage_mask) && mmu->bigpage_mask) ++ entry |= FIELD_PREP(MMMU_PTE_PAGESIZE_MASK, 1); ++ if (prot & IOMMU_WRITE) ++ entry |= MMMU_PTE_WRITEABLE; ++ ++ /* Ensure tables are cache-coherent with CPU */ ++ if (!mmu->dirty) { ++ dma_sync_sgtable_for_cpu(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = true; ++ } ++ ++ iova -= APERTURE_BASE; ++ for (p = iova >> MMU_PAGE_SHIFT; ++ p < (iova + bytes) >> MMU_PAGE_SHIFT; p++) { ++ mmu->nmapped_pages += !(mmu->tables[p]); ++ mmu->tables[p] = entry++; ++ } ++ } else if (iova + bytes > APERTURE_BASE || iova != pa) { ++ dev_warn(mmu->dev, "%s: iova=0x%lx pa=0x%llx size=0x%llx OUT OF RANGE!\n", ++ __func__, iova, ++ (unsigned long long)pa, (unsigned long long)bytes); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static size_t bcm2712_iommu_unmap(struct iommu_domain *domain, unsigned long iova, ++ size_t bytes, struct iommu_iotlb_gather *gather) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ ++ if (iova >= mmu->dma_iova_offset + APERTURE_BASE && ++ iova + bytes <= mmu->dma_iova_offset + APERTURE_TOP) { ++ unsigned int p; ++ ++ /* Record just the lower and upper bounds in "gather" */ ++ if (gather) { ++ bool empty = (gather->end <= gather->start); ++ ++ if (empty || gather->start < iova) ++ gather->start = iova; ++ if (empty || gather->end < iova + bytes) ++ gather->end = iova + bytes; ++ } ++ ++ /* Ensure tables are cache-coherent with CPU */ ++ if (!mmu->dirty) { ++ dma_sync_sgtable_for_cpu(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = true; ++ } ++ ++ /* Clear table entries, this marks the addresses as illegal */ ++ iova -= (mmu->dma_iova_offset + APERTURE_BASE); ++ for (p = iova >> MMU_PAGE_SHIFT; ++ p < (iova + bytes) >> MMU_PAGE_SHIFT; ++ p++) { ++ mmu->nmapped_pages -= !!(mmu->tables[p]); ++ mmu->tables[p] = 0; ++ } ++ } ++ ++ return bytes; ++} ++ ++static void bcm2712_iommu_sync_range(struct iommu_domain *domain, ++ unsigned long iova, size_t size) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ unsigned long iova_end; ++ unsigned int i, p4; ++ ++ if (!mmu || !mmu->dirty) ++ return; ++ ++ /* Ensure tables are cleaned from CPU cache or write-buffer */ ++ dma_sync_sgtable_for_device(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = false; ++ ++ /* Flush the shared TLB cache */ ++ if (mmu->cache) ++ bcm2712_iommu_cache_flush(mmu->cache); ++ ++ /* ++ * When flushing a large range or when nothing needs to be kept, ++ * it's quicker to use the"TLB_CLEAR" flag. Otherwise, invalidate ++ * TLB entries in lines of 4 words each. Each flush/clear operation ++ * should complete almost instantaneously. ++ */ ++ iova -= mmu->dma_iova_offset; ++ iova_end = min(APERTURE_TOP, iova + size); ++ iova = max(APERTURE_BASE, iova); ++ if (mmu->nmapped_pages == 0 || iova_end - iova >= APERTURE_SIZE / 8) { ++ MMU_WR(MMMU_CTRL_OFFSET, ++ MMMU_CTRL_CAP_EXCEEDED_ABORT_EN | ++ MMMU_CTRL_PT_INVALID_ABORT_EN | ++ MMMU_CTRL_WRITE_VIOLATION_ABORT_EN | ++ MMMU_CTRL_TLB_CLEAR | ++ MMMU_CTRL_STATS_ENABLE | ++ MMMU_CTRL_ENABLE); ++ for (i = 0; i < 1024; i++) { ++ if (!(MMMU_CTRL_TLB_CLEARING & MMU_RD(MMMU_CTRL_OFFSET))) ++ break; ++ cpu_relax(); ++ } ++ } else { ++ for (p4 = iova >> (MMU_PAGE_SHIFT + 2); ++ p4 < (iova_end + 3 * MMU_PAGE_SIZE) >> (MMU_PAGE_SHIFT + 2); ++ p4++) { ++ MMU_WR(MMMU_SHOOT_DOWN_OFFSET, ++ MMMU_SHOOT_DOWN_SHOOT + (p4 << 2)); ++ for (i = 0; i < 1024; i++) { ++ if (!(MMMU_SHOOT_DOWN_SHOOTING & MMU_RD(MMMU_SHOOT_DOWN_OFFSET))) ++ break; ++ cpu_relax(); ++ } ++ } ++ } ++} ++ ++static void bcm2712_iommu_sync(struct iommu_domain *domain, ++ struct iommu_iotlb_gather *gather) ++{ ++ bcm2712_iommu_sync_range(domain, gather->start, ++ gather->end - gather->start); ++} ++ ++static void bcm2712_iommu_sync_all(struct iommu_domain *domain) ++{ ++ bcm2712_iommu_sync_range(domain, APERTURE_BASE, APERTURE_SIZE); ++} ++ ++static phys_addr_t bcm2712_iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ u32 p; ++ ++ iova -= mmu->dma_iova_offset; ++ if (iova >= APERTURE_BASE && iova < APERTURE_TOP) { ++ p = (iova - APERTURE_BASE) >> MMU_PAGE_SHIFT; ++ p = mmu->tables[p] & 0x0FFFFFFFu; ++ return (((phys_addr_t)p) << MMU_PAGE_SHIFT) + (iova & (MMU_PAGE_SIZE - 1u)); ++ } else if (iova < APERTURE_BASE) { ++ return (phys_addr_t)iova; ++ } else { ++ return (phys_addr_t)-EINVAL; ++ } ++} ++ ++static void bcm2712_iommu_domain_free(struct iommu_domain *domain) ++{ ++ struct bcm2712_iommu_domain *mydomain = ++ container_of(domain, struct bcm2712_iommu_domain, base); ++ ++ kfree(mydomain); ++} ++ ++static const struct iommu_domain_ops bcm2712_iommu_domain_ops = { ++ .attach_dev = bcm2712_iommu_attach_dev, ++ .detach_dev = bcm2712_iommu_detach_dev, ++ .map = bcm2712_iommu_map, ++ .unmap = bcm2712_iommu_unmap, ++ .iotlb_sync = bcm2712_iommu_sync, ++ .iotlb_sync_map = bcm2712_iommu_sync_range, ++ .flush_iotlb_all = bcm2712_iommu_sync_all, ++ .iova_to_phys = bcm2712_iommu_iova_to_phys, ++ .free = bcm2712_iommu_domain_free, ++}; ++ ++static struct iommu_domain *bcm2712_iommu_domain_alloc(unsigned int type) ++{ ++ struct bcm2712_iommu_domain *domain; ++ ++ if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA) ++ return NULL; ++ ++ domain = kzalloc(sizeof(*domain), GFP_KERNEL); ++ if (!domain) ++ return NULL; ++ ++ domain->base.type = type; ++ domain->base.ops = &bcm2712_iommu_domain_ops; ++ domain->base.geometry.aperture_start = APERTURE_BASE; ++ domain->base.geometry.aperture_end = APERTURE_TOP - 1ul; ++ domain->base.geometry.force_aperture = true; ++ return &domain->base; ++} ++ ++static struct iommu_device *bcm2712_iommu_probe_device(struct device *dev) ++{ ++ struct bcm2712_iommu *mmu; ++ ++ /* ++ * For reasons I don't fully understand, we need to try both ++ * cases (dev_iommu_priv_get() and platform_get_drvdata()) ++ * in order to get both GPU and ISP-BE to probe successfully. ++ */ ++ mmu = dev_iommu_priv_get(dev); ++ if (!mmu) { ++ struct device_node *np; ++ struct platform_device *pdev; ++ ++ /* Ignore devices that don't have an "iommus" property with exactly one phandle */ ++ if (!dev->of_node || ++ of_property_count_elems_of_size(dev->of_node, "iommus", sizeof(phandle)) != 1) ++ return ERR_PTR(-ENODEV); ++ ++ np = of_parse_phandle(dev->of_node, "iommus", 0); ++ if (!np) ++ return ERR_PTR(-EINVAL); ++ ++ pdev = of_find_device_by_node(np); ++ of_node_put(np); ++ if (pdev) ++ mmu = platform_get_drvdata(pdev); ++ ++ if (!mmu) ++ return ERR_PTR(-ENODEV); ++ } ++ ++ dev_info(dev, "%s: MMU %s\n", __func__, dev_name(mmu->dev)); ++ dev_iommu_priv_set(dev, mmu); ++ return &mmu->iommu; ++} ++ ++static void bcm2712_iommu_release_device(struct device *dev) ++{ ++ dev_iommu_priv_set(dev, NULL); ++} ++ ++static struct iommu_group *bcm2712_iommu_device_group(struct device *dev) ++{ ++ struct bcm2712_iommu *mmu = dev_iommu_priv_get(dev); ++ ++ if (!mmu || !mmu->group) ++ return ERR_PTR(-EINVAL); ++ ++ dev_info(dev, "%s: MMU %s\n", __func__, dev_name(mmu->dev)); ++ return iommu_group_ref_get(mmu->group); ++} ++ ++static int bcm2712_iommu_of_xlate(struct device *dev, ++ struct of_phandle_args *args) ++{ ++ struct platform_device *iommu_dev; ++ struct bcm2712_iommu *mmu; ++ ++ iommu_dev = of_find_device_by_node(args->np); ++ mmu = platform_get_drvdata(iommu_dev); ++ dev_iommu_priv_set(dev, mmu); ++ dev_info(dev, "%s: MMU %s\n", __func__, dev_name(mmu->dev)); ++ ++ return 0; ++} ++ ++static bool bcm2712_iommu_capable(struct device *dev, enum iommu_cap cap) ++{ ++ return false; ++} ++ ++static const struct iommu_ops bcm2712_iommu_ops = { ++ .capable = bcm2712_iommu_capable, ++ .domain_alloc = bcm2712_iommu_domain_alloc, ++ .probe_device = bcm2712_iommu_probe_device, ++ .release_device = bcm2712_iommu_release_device, ++ .device_group = bcm2712_iommu_device_group, ++ /* Advertise native page sizes as well as 2M, 16K which Linux may prefer */ ++ .pgsize_bitmap = (SZ_4M | SZ_2M | SZ_1M | SZ_64K | SZ_16K | SZ_4K), ++ .default_domain_ops = &bcm2712_iommu_domain_ops, ++ .of_xlate = bcm2712_iommu_of_xlate, ++}; ++ ++static int bcm2712_iommu_probe(struct platform_device *pdev) ++{ ++ struct bcm2712_iommu *mmu; ++ struct bcm2712_iommu_cache *cache = NULL; ++ int ret; ++ ++ /* First of all, check for an IOMMU shared cache */ ++ if (pdev->dev.of_node) { ++ struct device_node *cache_np; ++ struct platform_device *cache_pdev; ++ ++ cache_np = of_parse_phandle(pdev->dev.of_node, "cache", 0); ++ if (cache_np) { ++ cache_pdev = of_find_device_by_node(cache_np); ++ of_node_put(cache_np); ++ if (cache_pdev && !IS_ERR(cache_pdev)) ++ cache = platform_get_drvdata(cache_pdev); ++ if (!cache) ++ return -EPROBE_DEFER; ++ } ++ } ++ ++ /* Allocate private data */ ++ mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL); ++ if (!mmu) ++ return -ENOMEM; ++ ++ mmu->name = dev_name(&pdev->dev); ++ mmu->dev = &pdev->dev; ++ mmu->cache = cache; ++ platform_set_drvdata(pdev, mmu); ++ spin_lock_init(&mmu->hw_lock); ++ ++ /* ++ * XXX When an IOMMU is downstream of a PCIe RC or some other chip/bus ++ * and serves some of the masters thereon (others using pass-through), ++ * we seem to fumble and lose the "dma-ranges" address offset for ++ * masters using IOMMU. This property restores it, where needed. ++ */ ++ if (!pdev->dev.of_node || ++ of_property_read_u64(pdev->dev.of_node, "dma-iova-offset", ++ &mmu->dma_iova_offset)) ++ mmu->dma_iova_offset = 0; ++ ++ /* ++ * The IOMMU is itself a device that allocates DMA-able memory ++ * to hold its translation tables. Provided the IOVA aperture ++ * is no larger than 4 GBytes (so that the L1 table fits within ++ * a single 4K page), we don't need the tables to be contiguous. ++ * Assume we can address at least 36 bits (64 GB). ++ */ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); ++ WARN_ON(ret); ++ mmu->sgt = dma_alloc_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ DMA_TO_DEVICE, GFP_KERNEL, ++ DMA_ATTR_ALLOC_SINGLE_PAGES); ++ if (!mmu->sgt) { ++ ret = -ENOMEM; ++ goto done_err; ++ } ++ mmu->tables = dma_vmap_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ mmu->sgt); ++ if (!mmu->tables) { ++ ret = -ENOMEM; ++ goto done_err; ++ } ++ ++ /* Get IOMMU registers */ ++ mmu->reg_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mmu->reg_base)) { ++ dev_err(&pdev->dev, "Failed to get IOMMU registers address\n"); ++ ret = PTR_ERR(mmu->reg_base); ++ goto done_err; ++ } ++ ++ /* Stuff */ ++ mmu->group = iommu_group_alloc(); ++ if (IS_ERR(mmu->group)) { ++ ret = PTR_ERR(mmu->group); ++ mmu->group = NULL; ++ goto done_err; ++ } ++ ret = iommu_device_sysfs_add(&mmu->iommu, mmu->dev, NULL, mmu->name); ++ if (ret) ++ goto done_err; ++ ++ /* Initialize table and hardware */ ++ bcm2712_iommu_init(mmu); ++ ret = iommu_device_register(&mmu->iommu, &bcm2712_iommu_ops, &pdev->dev); ++ ++ dev_info(&pdev->dev, "%s: Success\n", __func__); ++ return 0; ++ ++done_err: ++ dev_info(&pdev->dev, "%s: Failure %d\n", __func__, ret); ++ if (mmu->group) ++ iommu_group_put(mmu->group); ++ if (mmu->tables) ++ dma_vunmap_noncontiguous(&pdev->dev, ++ (void *)(mmu->tables)); ++ mmu->tables = NULL; ++ if (mmu->sgt) ++ dma_free_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ mmu->sgt, DMA_TO_DEVICE); ++ mmu->sgt = NULL; ++ kfree(mmu); ++ return ret; ++} ++ ++static int bcm2712_iommu_remove(struct platform_device *pdev) ++{ ++ struct bcm2712_iommu *mmu = platform_get_drvdata(pdev); ++ ++ if (mmu->reg_base) ++ MMU_WR(MMMU_CTRL_OFFSET, 0); /* disable the MMU */ ++ if (mmu->sgt) ++ dma_free_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ mmu->sgt, DMA_TO_DEVICE); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm2712_iommu_of_match[] = { ++ { ++ . compatible = "brcm,bcm2712-iommu" ++ }, ++ { /* sentinel */ }, ++}; ++ ++static struct platform_driver bcm2712_iommu_driver = { ++ .probe = bcm2712_iommu_probe, ++ .remove = bcm2712_iommu_remove, ++ .driver = { ++ .name = "bcm2712-iommu", ++ .of_match_table = bcm2712_iommu_of_match ++ }, ++}; ++ ++builtin_platform_driver(bcm2712_iommu_driver); +--- /dev/null ++++ b/drivers/iommu/bcm2712-iommu.h +@@ -0,0 +1,45 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * IOMMU driver for BCM2712 ++ * ++ * Copyright (c) 2023 Raspberry Pi Ltd. ++ */ ++ ++#ifndef _BCM2712_IOMMU_H ++#define _BCM2712_IOMMU_H ++ ++#include ++#include ++ ++struct bcm2712_iommu_cache { ++ struct device *dev; ++ spinlock_t hw_lock; /* to protect HW registers */ ++ void __iomem *reg_base; ++}; ++ ++void bcm2712_iommu_cache_flush(struct bcm2712_iommu_cache *cache); ++ ++struct bcm2712_iommu { ++ struct device *dev; ++ struct iommu_device iommu; ++ struct iommu_group *group; ++ struct bcm2712_iommu_domain *domain; ++ char const *name; ++ struct sg_table *sgt; /* allocated memory for page tables */ ++ u32 *tables; /* kernel mapping for page tables */ ++ struct bcm2712_iommu_cache *cache; ++ spinlock_t hw_lock; /* to protect HW registers */ ++ void __iomem *reg_base; ++ u64 dma_iova_offset; /* Hack for IOMMU attached to PCIe RC */ ++ u32 bigpage_mask; ++ u32 superpage_mask; ++ unsigned int nmapped_pages; ++ bool dirty; /* true when tables are oriented towards CPU */ ++}; ++ ++struct bcm2712_iommu_domain { ++ struct iommu_domain base; ++ struct bcm2712_iommu *mmu; ++}; ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-0918-irqchip-irq-brcmstb-l2-Add-config-for-2711-controlle.patch b/target/linux/bcm27xx/patches-6.1/950-0918-irqchip-irq-brcmstb-l2-Add-config-for-2711-controlle.patch new file mode 100644 index 0000000000..5ea212d4a7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0918-irqchip-irq-brcmstb-l2-Add-config-for-2711-controlle.patch @@ -0,0 +1,73 @@ +From fa4d4ed28c92cf4470e518f1a7362dc7941632d7 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 28 Jun 2023 16:24:29 +0100 +Subject: [PATCH] irqchip/irq-brcmstb-l2: Add config for 2711 controller + +We currently see these regularly: +[ 25.157560] irq 31, desc: 00000000c15e6d2c, depth: 0, count: 0, unhandled: 0 +[ 25.164658] ->handle_irq(): 00000000b1775675, brcmstb_l2_intc_irq_handle+0x0/0x1a8 +[ 25.172352] ->irq_data.chip(): 00000000fea59f1c, gic_chip_mode1+0x0/0x108 +[ 25.179166] ->action(): 000000003eda6d6f +[ 25.183096] ->action->handler(): 000000002c09e646, bad_chained_irq+0x0/0x58 +[ 25.190084] IRQ_LEVEL set +[ 25.193142] IRQ_NOPROBE set +[ 25.196198] IRQ_NOREQUEST set +[ 25.199255] IRQ_NOTHREAD set + +with: +$ cat /proc/interrupts | grep 31: + 31: 1 0 0 0 GICv2 129 Level (null) + +The interrupt is described in DT with IRQ_TYPE_LEVEL_HIGH + +But the current compatible string uses the controller in edge triggered mode +(as that config matches our register layout). + +Add a new compatible structure for level driven interrupt with our register layout. + +We had already been using this compatible string in device tree, so no change needed +there. + +Signed-off-by: Dom Cobley +--- + drivers/irqchip/irq-brcmstb-l2.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/irqchip/irq-brcmstb-l2.c ++++ b/drivers/irqchip/irq-brcmstb-l2.c +@@ -52,6 +52,16 @@ static const struct brcmstb_intc_init_pa + .cpu_mask_clear = 0x0C + }; + ++/* Register offsets in the 2711 L2 level interrupt controller */ ++static const struct brcmstb_intc_init_params l2_2711_lvl_intc_init = { ++ .handler = handle_level_irq, ++ .cpu_status = 0x00, ++ .cpu_clear = 0x08, ++ .cpu_mask_status = 0x0c, ++ .cpu_mask_set = 0x10, ++ .cpu_mask_clear = 0x14 ++}; ++ + /* L2 intc private data structure */ + struct brcmstb_l2_intc_data { + struct irq_domain *domain; +@@ -286,11 +296,18 @@ static int __init brcmstb_l2_lvl_intc_of + return brcmstb_l2_intc_of_init(np, parent, &l2_lvl_intc_init); + } + ++static int __init brcmstb_l2_2711_lvl_intc_of_init(struct device_node *np, ++ struct device_node *parent) ++{ ++ return brcmstb_l2_intc_of_init(np, parent, &l2_2711_lvl_intc_init); ++} ++ + IRQCHIP_PLATFORM_DRIVER_BEGIN(brcmstb_l2) + IRQCHIP_MATCH("brcm,l2-intc", brcmstb_l2_edge_intc_of_init) + IRQCHIP_MATCH("brcm,hif-spi-l2-intc", brcmstb_l2_edge_intc_of_init) + IRQCHIP_MATCH("brcm,upg-aux-aon-l2-intc", brcmstb_l2_edge_intc_of_init) + IRQCHIP_MATCH("brcm,bcm7271-l2-intc", brcmstb_l2_lvl_intc_of_init) ++IRQCHIP_MATCH("brcm,bcm2711-l2-intc", brcmstb_l2_2711_lvl_intc_of_init) + IRQCHIP_PLATFORM_DRIVER_END(brcmstb_l2) + MODULE_DESCRIPTION("Broadcom STB generic L2 interrupt controller"); + MODULE_LICENSE("GPL v2"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0919-rtc-rtc-rpi-Add-simple-RTC-driver-for-Raspberry-Pi.patch b/target/linux/bcm27xx/patches-6.1/950-0919-rtc-rtc-rpi-Add-simple-RTC-driver-for-Raspberry-Pi.patch new file mode 100644 index 0000000000..e2b8c6c6a1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0919-rtc-rtc-rpi-Add-simple-RTC-driver-for-Raspberry-Pi.patch @@ -0,0 +1,237 @@ +From 222dedcdc09247126d39364a614ff2019789f52a Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Fri, 7 Jul 2023 20:00:45 +0100 +Subject: [PATCH] rtc: rtc-rpi: Add simple RTC driver for Raspberry Pi + +This supports setting and reading the real time clock +and supports wakeup alarms. + +To support wake up alarms you want this bootloader config: + POWER_OFF_ON_HALT=1 + WAKE_ON_GPIO=0 + +You can test with: + echo +600 | sudo tee /sys/class/rtc/rtc0/wakealarm + sudo halt + +That will halt (in an almost no power state), +then wake and restart after 10 minutes. + +Signed-off-by: Dom Cobley +--- + drivers/rtc/Kconfig | 11 +++ + drivers/rtc/Makefile | 1 + + drivers/rtc/rtc-rpi.c | 177 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 189 insertions(+) + create mode 100644 drivers/rtc/rtc-rpi.c + +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -223,6 +223,17 @@ config RTC_DRV_AC100 + This driver can also be built as a module. If so, the module + will be called rtc-ac100. + ++config RTC_DRV_RPI ++ tristate "Raspberry Pi RTC" ++ depends on ARCH_BRCMSTB || COMPILE_TEST ++ default ARCH_BRCMSTB ++ help ++ If you say yes here you get support for the RTC found on ++ Raspberry Pi devices. ++ ++ This driver can also be built as a module. If so, the module ++ will be called rtc-rpi. ++ + config RTC_DRV_BRCMSTB + tristate "Broadcom STB wake-timer" + depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -140,6 +140,7 @@ obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5 + obj-$(CONFIG_RTC_DRV_RC5T619) += rtc-rc5t619.o + obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o + obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o ++obj-$(CONFIG_RTC_DRV_RPI) += rtc-rpi.o + obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o + obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o + obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o +--- /dev/null ++++ b/drivers/rtc/rtc-rpi.c +@@ -0,0 +1,177 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/** ++ * rtc-rpi.c ++ * ++ * RTC driver using firmware mailbox ++ * Supports battery backed RTC and wake alarms ++ * ++ * Based on rtc-meson-vrtc by Neil Armstrong ++ * ++ * Copyright (c) 2023, Raspberry Pi Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++struct rpi_rtc_data { ++ struct rtc_device *rtc; ++ struct rpi_firmware *fw; ++}; ++ ++#define RPI_FIRMWARE_GET_RTC_REG 0x00030087 ++#define RPI_FIRMWARE_SET_RTC_REG 0x00038087 ++enum {RTC_TIME, RTC_ALARM, RTC_ALARM_PENDING, RTC_ALARM_ENABLE}; ++ ++static int rpi_rtc_read_time(struct device *dev, struct rtc_time *tm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_TIME}; ++ int err; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ rtc_time64_to_tm(data[1], tm); ++ return err; ++} ++ ++static int rpi_rtc_set_time(struct device *dev, struct rtc_time *tm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_TIME, rtc_tm_to_time64(tm)}; ++ ++ return rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++} ++ ++static int rpi_rtc_alarm_irq_is_enabled(struct device *dev, unsigned char *enabled) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM_ENABLE}; ++ s32 err = 0; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ *enabled = data[1] & 0x1; ++ return err; ++} ++ ++static int rpi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM_ENABLE, enabled}; ++ ++ return rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++} ++ ++static int rpi_rtc_alarm_clear_pending(struct device *dev) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM_PENDING, 1}; ++ ++ return rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++} ++ ++static int rpi_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM}; ++ s32 err = 0; ++ ++ err = rpi_rtc_alarm_irq_is_enabled(dev, &alarm->enabled); ++ if (!err) ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ rtc_time64_to_tm(data[1], &alarm->time); ++ ++ return err; ++} ++ ++static int rpi_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM, rtc_tm_to_time64(&alarm->time)}; ++ int err; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++ ++ if (err == 0) ++ err = rpi_rtc_alarm_irq_enable(dev, alarm->enabled); ++ ++ return err; ++} ++ ++static const struct rtc_class_ops rpi_rtc_ops = { ++ .read_time = rpi_rtc_read_time, ++ .set_time = rpi_rtc_set_time, ++ .read_alarm = rpi_rtc_read_alarm, ++ .set_alarm = rpi_rtc_set_alarm, ++ .alarm_irq_enable = rpi_rtc_alarm_irq_enable, ++}; ++ ++static int rpi_rtc_probe(struct platform_device *pdev) ++{ ++ struct rpi_rtc_data *vrtc; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ int ret; ++ ++ fw_node = of_parse_phandle(np, "firmware", 0); ++ if (!fw_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; ++ ++ vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL); ++ if (!vrtc) ++ return -ENOMEM; ++ ++ vrtc->fw = fw; ++ ++ device_init_wakeup(&pdev->dev, 1); ++ ++ platform_set_drvdata(pdev, vrtc); ++ ++ vrtc->rtc = devm_rtc_allocate_device(&pdev->dev); ++ if (IS_ERR(vrtc->rtc)) ++ return PTR_ERR(vrtc->rtc); ++ ++ set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, vrtc->rtc->features); ++ clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, vrtc->rtc->features); ++ ++ vrtc->rtc->ops = &rpi_rtc_ops; ++ ret = devm_rtc_register_device(vrtc->rtc); ++ ++ rpi_rtc_alarm_clear_pending(dev); ++ return ret; ++} ++ ++static const struct of_device_id rpi_rtc_dt_match[] = { ++ { .compatible = "raspberrypi,rpi-rtc"}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rpi_rtc_dt_match); ++ ++static struct platform_driver rpi_rtc_driver = { ++ .probe = rpi_rtc_probe, ++ .driver = { ++ .name = "rpi-rtc", ++ .of_match_table = rpi_rtc_dt_match, ++ }, ++}; ++ ++module_platform_driver(rpi_rtc_driver); ++ ++MODULE_DESCRIPTION("Raspberry Pi RTC driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0920-dt-bindings-rtc-new-binding-for-Raspberry-Pi-RTC-dri.patch b/target/linux/bcm27xx/patches-6.1/950-0920-dt-bindings-rtc-new-binding-for-Raspberry-Pi-RTC-dri.patch new file mode 100644 index 0000000000..f4c630cf09 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0920-dt-bindings-rtc-new-binding-for-Raspberry-Pi-RTC-dri.patch @@ -0,0 +1,35 @@ +From ff2c2f67689e10ad66c1e33ae6a7552d82ac983c Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Fri, 7 Jul 2023 20:16:06 +0100 +Subject: [PATCH] dt-bindings: rtc: new binding for Raspberry Pi RTC driver + +Add binding for the new RTC driver for Raspberry Pi. +This platform has an RTC managed by firmware, and this RTC +driver provides the simple mailbox interface to access it. + +Signed-off-by: Dom Cobley +--- + .../devicetree/bindings/rtc/rtc-rpi.txt | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + create mode 100644 Documentation/devicetree/bindings/rtc/rtc-rpi.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/rtc/rtc-rpi.txt +@@ -0,0 +1,17 @@ ++* Raspberry Pi RTC ++ ++This is a Linux interface to an RTC managed by firmware, hence it's ++virtual from a Linux perspective. ++ ++The interface uses the firmware mailbox api to access the RTC registers. ++ ++Required properties: ++compatible: should be "raspberrypi,rpi-rtc" ++firmware: Reference to the RPi firmware device node. ++ ++Example: ++ ++ rpi_rtc: rpi_rtc { ++ compatible = "raspberrypi,rpi-rtc"; ++ firmware = <&firmware>; ++ }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch b/target/linux/bcm27xx/patches-6.1/950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch new file mode 100644 index 0000000000..205806cdfd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch @@ -0,0 +1,164 @@ +From 96a8a4776cb142f5d2bb7f6379df9af40e727c0b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 11 Jul 2023 10:17:29 +0100 +Subject: [PATCH] hwmon: (pwm-fan) Add fan speed register support + +Some platforms include a fan-speed register that reports RPM directly +as an alternative to counting interrupts from the fan tachometer input. +Add support for reading a register at a given offset (rpm-offset) within +a block declared in another node (rpm-regmap). This indirection allows +the usual address mapping to be performed, and for address sharing with +another driver. + +Signed-off-by: Phil Elwell +--- + drivers/hwmon/pwm-fan.c | 59 ++++++++++++++++++++++++++++++++++++----- + 1 file changed, 52 insertions(+), 7 deletions(-) + +--- a/drivers/hwmon/pwm-fan.c ++++ b/drivers/hwmon/pwm-fan.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -51,6 +52,9 @@ struct pwm_fan_ctx { + ktime_t sample_start; + struct timer_list rpm_timer; + ++ void __iomem *rpm_regbase; ++ unsigned int rpm_offset; ++ + unsigned int pwm_value; + unsigned int pwm_fan_state; + unsigned int pwm_fan_max_state; +@@ -61,6 +65,10 @@ struct pwm_fan_ctx { + struct hwmon_channel_info fan_channel; + }; + ++static const u32 rpm_reg_channel_config[] = { ++ HWMON_F_INPUT, 0 ++}; ++ + /* This handler assumes self resetting edge triggered interrupt. */ + static irqreturn_t pulse_handler(int irq, void *dev_id) + { +@@ -335,7 +343,10 @@ static int pwm_fan_read(struct device *d + } + return -EOPNOTSUPP; + case hwmon_fan: +- *val = ctx->tachs[channel].rpm; ++ if (ctx->rpm_regbase) ++ *val = (long)readl(ctx->rpm_regbase + ctx->rpm_offset); ++ else ++ *val = ctx->tachs[channel].rpm; + return 0; + + default: +@@ -470,6 +481,7 @@ static void pwm_fan_cleanup(void *__ctx) + /* Switch off everything */ + ctx->enable_mode = pwm_disable_reg_disable; + pwm_fan_power_off(ctx); ++ iounmap(ctx->rpm_regbase); + } + + static int pwm_fan_probe(struct platform_device *pdev) +@@ -534,10 +546,23 @@ static int pwm_fan_probe(struct platform + return ret; + + ctx->tach_count = platform_irq_count(pdev); ++ if (ctx->tach_count == 0) { ++ struct device_node *rpm_node; ++ ++ rpm_node = of_parse_phandle(dev->of_node, "rpm-regmap", 0); ++ if (rpm_node) ++ ctx->rpm_regbase = of_iomap(rpm_node, 0); ++ } ++ + if (ctx->tach_count < 0) + return dev_err_probe(dev, ctx->tach_count, + "Could not get number of fan tachometer inputs\n"); +- dev_dbg(dev, "%d fan tachometer inputs\n", ctx->tach_count); ++ if (IS_ERR(ctx->rpm_regbase)) ++ return dev_err_probe(dev, PTR_ERR(ctx->rpm_regbase), ++ "Could not get rpm reg\n"); ++ ++ dev_dbg(dev, "%d fan tachometer inputs, %d rpm regmap\n", ctx->tach_count, ++ !!ctx->rpm_regbase); + + if (ctx->tach_count) { + channel_count++; /* We also have a FAN channel. */ +@@ -554,12 +579,24 @@ static int pwm_fan_probe(struct platform + if (!fan_channel_config) + return -ENOMEM; + ctx->fan_channel.config = fan_channel_config; ++ } else if (ctx->rpm_regbase) { ++ channel_count++; /* We also have a FAN channel. */ ++ ctx->fan_channel.type = hwmon_fan; ++ ctx->fan_channel.config = rpm_reg_channel_config; ++ ++ if (of_property_read_u32(pdev->dev.of_node, "rpm-offset", &ctx->rpm_offset)) { ++ dev_err(&pdev->dev, "unable to read 'rpm-offset'"); ++ ret = -EINVAL; ++ goto error; ++ } + } + + channels = devm_kcalloc(dev, channel_count + 1, + sizeof(struct hwmon_channel_info *), GFP_KERNEL); +- if (!channels) +- return -ENOMEM; ++ if (!channels) { ++ ret = -ENOMEM; ++ goto error; ++ } + + channels[0] = HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE); + +@@ -602,6 +639,8 @@ static int pwm_fan_probe(struct platform + mod_timer(&ctx->rpm_timer, jiffies + HZ); + + channels[1] = &ctx->fan_channel; ++ } else if (ctx->rpm_regbase) { ++ channels[1] = &ctx->fan_channel; + } + + ctx->info.ops = &pwm_fan_hwmon_ops; +@@ -611,12 +650,13 @@ static int pwm_fan_probe(struct platform + ctx, &ctx->info, NULL); + if (IS_ERR(hwmon)) { + dev_err(dev, "Failed to register hwmon device\n"); +- return PTR_ERR(hwmon); ++ ret = PTR_ERR(hwmon); ++ goto error; + } + + ret = pwm_fan_of_get_cooling_data(dev, ctx); + if (ret) +- return ret; ++ goto error; + + ctx->pwm_fan_state = ctx->pwm_fan_max_state; + if (IS_ENABLED(CONFIG_THERMAL)) { +@@ -627,12 +667,17 @@ static int pwm_fan_probe(struct platform + dev_err(dev, + "Failed to register pwm-fan as cooling device: %d\n", + ret); +- return ret; ++ goto error; + } + ctx->cdev = cdev; + } + + return 0; ++ ++error: ++ if (ctx->rpm_regbase) ++ iounmap(ctx->rpm_regbase); ++ return ret; + } + + static void pwm_fan_shutdown(struct platform_device *pdev) diff --git a/target/linux/bcm27xx/patches-6.1/950-0923-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch b/target/linux/bcm27xx/patches-6.1/950-0923-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch new file mode 100644 index 0000000000..2972c57fd7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0923-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch @@ -0,0 +1,63 @@ +From 07419175fdb507be2c9d3aaf4b7d18306a336348 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 2 Aug 2023 11:38:03 +0100 +Subject: [PATCH] dt-bindings: input: Add bindings for raspberrypi-button + +Add bindings for the firmware-based button driver. + +Signed-off-by: Phil Elwell +--- + .../input/raspberrypi,firmware-button.yaml | 47 +++++++++++++++++++ + 1 file changed, 47 insertions(+) + create mode 100644 Documentation/devicetree/bindings/input/raspberrypi,firmware-button.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/input/raspberrypi,firmware-button.yaml +@@ -0,0 +1,47 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/input/raspberrypi,firmware-button.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Raspberry Pi firmware buttons ++ ++maintainers: ++ - Phil Elwell ++ ++description: > ++ The Raspberry Pi 5 firmware exposes the state of the power button. The ++ raspberrypi-button driver generates a keycode when it is pressed. ++ ++properties: ++ compatible: ++ enum: ++ - raspberrypi,firmware-button ++ ++ id: ++ description: A numeric identifier of the button ++ ++ label: ++ description: Descriptive name of the button. ++ ++ linux,code: ++ description: Key code to emit. ++ ++required: ++ - compatible ++ - linux,code ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ pwr_button: pwr_button { ++ compatible = "raspberrypi,firmware-button"; ++ id = ; ++ label = "pwr_button"; ++ linux,code = <116>; // KEY_POWER ++ }; ++ ++... diff --git a/target/linux/bcm27xx/patches-6.1/950-0924-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch b/target/linux/bcm27xx/patches-6.1/950-0924-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch new file mode 100644 index 0000000000..e8fea23ce8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0924-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch @@ -0,0 +1,27 @@ +From 93c8947bc7813b49fe27a5251eef97c6df1e14c6 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 2 Aug 2023 15:01:29 +0100 +Subject: [PATCH] dt-bindings: input: Add bindings for raspberrypi-button + +Add bindings for the firmware-based button driver. + +Signed-off-by: Phil Elwell +--- + include/dt-bindings/input/raspberrypi-button.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + create mode 100644 include/dt-bindings/input/raspberrypi-button.h + +--- /dev/null ++++ b/include/dt-bindings/input/raspberrypi-button.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ ++/* ++ * This header provides constants the raspberrypi-button driver. ++ */ ++ ++#ifndef _DT_BINDINGS_RASPBERRYPI_BUTTON_H ++#define _DT_BINDINGS_RASPBERRYPI_BUTTON_H ++ ++#define RASPBERRYPI_BUTTON_POWER 0 ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-0925-Input-Add-raspberrypi-button-firmware-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0925-Input-Add-raspberrypi-button-firmware-driver.patch new file mode 100644 index 0000000000..76a9261a68 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0925-Input-Add-raspberrypi-button-firmware-driver.patch @@ -0,0 +1,197 @@ +From 7c0d40384b0648030d5202114d90239b8db7d4e0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 2 Aug 2023 11:30:48 +0100 +Subject: [PATCH] Input: Add raspberrypi-button firmware driver + +Raspberry Pi 5s have a power/suspend button that is only accessible to +the firmware. Add a driver to read it and generate key events. + +Signed-off-by: Phil Elwell +--- + drivers/input/misc/Kconfig | 10 ++ + drivers/input/misc/Makefile | 1 + + drivers/input/misc/raspberrypi-button.c | 138 +++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 4 files changed, 150 insertions(+) + create mode 100644 drivers/input/misc/raspberrypi-button.c + +--- a/drivers/input/misc/Kconfig ++++ b/drivers/input/misc/Kconfig +@@ -918,6 +918,16 @@ config INPUT_RT5120_PWRKEY + To compile this driver as a module, choose M here. the module will + be called rt5120-pwrkey. + ++config INPUT_RASPBERRYPI_BUTTON ++ tristate "Raspberry Pi button support" ++ depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) ++ help ++ This enables support for firmware-controlled buttons on Raspberry ++ Pi devices. ++ ++ To compile this driver as a module, choose M here. the module will ++ be called raspberrypi-button. ++ + config INPUT_STPMIC1_ONKEY + tristate "STPMIC1 PMIC Onkey support" + depends on MFD_STPMIC1 +--- a/drivers/input/misc/Makefile ++++ b/drivers/input/misc/Makefile +@@ -70,6 +70,7 @@ obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += + obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o + obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o + obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o ++obj-$(CONFIG_INPUT_RASPBERRYPI_BUTTON) += raspberrypi-button.o + obj-$(CONFIG_INPUT_RT5120_PWRKEY) += rt5120-pwrkey.o + obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o + obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o +--- /dev/null ++++ b/drivers/input/misc/raspberrypi-button.c +@@ -0,0 +1,138 @@ ++// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 ++/* ++ * Driver for Raspberry Pi power button ++ * ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ * ++ * This driver is based on drivers/hwmon/raspberrypi-hwmon.c and ++ * input/misc/pm8941-pwrkey.c/ - see original files for copyright information ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct rpi_button { ++ struct device *dev; ++ struct rpi_firmware *fw; ++ struct input_dev *input; ++ struct delayed_work poll_work; ++ unsigned long poll_rate; ++ const char *name; ++ u32 id; ++ u32 code; ++}; ++ ++static void button_poll(struct work_struct *work) ++{ ++ struct rpi_button *button; ++ u32 value; ++ int err; ++ ++ button = container_of(work, struct rpi_button, ++ poll_work.work); ++ ++ value = BIT(button->id); ++ err = rpi_firmware_property(button->fw, RPI_FIRMWARE_GET_BUTTONS_PRESSED, ++ &value, sizeof(value)); ++ if (err) { ++ dev_err_once(button->dev, "GET_BUTTON_PRESSED not implemented?\n"); ++ return; ++ } ++ ++ if (value & BIT(button->id)) { ++ input_event(button->input, EV_KEY, button->code, 1); ++ input_sync(button->input); ++ input_event(button->input, EV_KEY, button->code, 0); ++ input_sync(button->input); ++ } ++ ++ schedule_delayed_work(&button->poll_work, button->poll_rate); ++} ++ ++static int rpi_button_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rpi_button *button; ++ int err; ++ ++ button = devm_kzalloc(dev, sizeof(*button), GFP_KERNEL); ++ if (!button) ++ return -ENOMEM; ++ ++ button->dev = dev; ++ ++ /* Get the firmware pointer from our parent */ ++ button->fw = dev_get_drvdata(dev->parent); ++ ++ if (device_property_read_u32(dev, "id", &button->id)) ++ button->id = RASPBERRYPI_BUTTON_POWER; ++ ++ if (device_property_read_string(dev, "label", &button->name)) ++ button->name = "raspberrypi-button"; ++ ++ if (device_property_read_u32(dev, "linux,code", &button->code)) { ++ dev_err(&pdev->dev, "no linux,code property\n"); ++ return -EINVAL; ++ } ++ ++ button->input = devm_input_allocate_device(dev); ++ if (!button->input) { ++ dev_dbg(&pdev->dev, "unable to allocate input device\n"); ++ return -ENOMEM; ++ } ++ ++ input_set_capability(button->input, EV_KEY, button->code); ++ ++ button->input->name = button->name; ++ button->input->phys = "raspberrypi-button/input0"; ++ button->input->dev.parent = dev; ++ button->poll_rate = HZ; ++ ++ err = input_register_device(button->input); ++ if (err) { ++ dev_err(&pdev->dev, "failed to register input device: %d\n", ++ err); ++ return err; ++ } ++ ++ err = devm_delayed_work_autocancel(dev, &button->poll_work, ++ button_poll); ++ if (err) ++ return err; ++ ++ platform_set_drvdata(pdev, button); ++ schedule_delayed_work(&button->poll_work, button->poll_rate); ++ ++ return 0; ++} ++ ++static const struct of_device_id rpi_button_match[] = { ++ { .compatible = "raspberrypi,firmware-button", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, rpi_button_match); ++ ++static struct platform_driver rpi_button_driver = { ++ .probe = rpi_button_probe, ++ .driver = { ++ .name = "raspberrypi-button", ++ .of_match_table = of_match_ptr(rpi_button_match), ++ }, ++}; ++module_platform_driver(rpi_button_driver); ++ ++MODULE_AUTHOR("Phil Elwell "); ++MODULE_DESCRIPTION("Raspberry Pi button driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -98,6 +98,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_GET_REBOOT_FLAGS = 0x00030064, + RPI_FIRMWARE_SET_REBOOT_FLAGS = 0x00038064, + RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066, ++ RPI_FIRMWARE_GET_BUTTONS_PRESSED = 0x00030088, + + /* Dispmanx TAGS */ + RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, diff --git a/target/linux/bcm27xx/patches-6.1/950-0926-dt-bindings-update-rpi-rtc-binding.patch b/target/linux/bcm27xx/patches-6.1/950-0926-dt-bindings-update-rpi-rtc-binding.patch new file mode 100644 index 0000000000..ffc5cc1a9d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0926-dt-bindings-update-rpi-rtc-binding.patch @@ -0,0 +1,29 @@ +From a7a3679a148e40879f1ce77580d9edf64cb5b51c Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 18 Sep 2023 16:33:06 +0100 +Subject: [PATCH] dt: bindings: update rpi-rtc binding + +Add property for bcm2712 firmware RTC driver charger control + +Signed-off-by: Jonathan Bell +--- + Documentation/devicetree/bindings/rtc/rtc-rpi.txt | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/Documentation/devicetree/bindings/rtc/rtc-rpi.txt ++++ b/Documentation/devicetree/bindings/rtc/rtc-rpi.txt +@@ -9,9 +9,14 @@ Required properties: + compatible: should be "raspberrypi,rpi-rtc" + firmware: Reference to the RPi firmware device node. + ++Optional property: ++trickle-charge-microvolt: specify a trickle charge voltage for the backup ++ battery in microvolts. ++ + Example: + + rpi_rtc: rpi_rtc { + compatible = "raspberrypi,rpi-rtc"; + firmware = <&firmware>; ++ trickle-charge-microvolt = <3000000>; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0927-drivers-rtc-rpi-add-battery-charge-circuit-control-a.patch b/target/linux/bcm27xx/patches-6.1/950-0927-drivers-rtc-rpi-add-battery-charge-circuit-control-a.patch new file mode 100644 index 0000000000..dae0a1cbff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0927-drivers-rtc-rpi-add-battery-charge-circuit-control-a.patch @@ -0,0 +1,153 @@ +From 33b514cb16dbf13395a0becf7442d19676ae4224 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Fri, 15 Sep 2023 17:33:03 +0100 +Subject: [PATCH] drivers: rtc-rpi: add battery charge circuit control and + readback + +Parse devicetree for a charger voltage and apply it. If nonzero and a +valid voltage, the firmware will enable charging, otherwise the charger +circuit is disabled. + +Add sysfs attributes to read back the supported charge voltage range, +the measured battery voltage, and the charger setpoint. + +Signed-off-by: Jonathan Bell +--- + drivers/rtc/rtc-rpi.c | 106 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 103 insertions(+), 3 deletions(-) + +--- a/drivers/rtc/rtc-rpi.c ++++ b/drivers/rtc/rtc-rpi.c +@@ -19,11 +19,22 @@ + struct rpi_rtc_data { + struct rtc_device *rtc; + struct rpi_firmware *fw; ++ u32 bbat_vchg_microvolts; + }; + + #define RPI_FIRMWARE_GET_RTC_REG 0x00030087 + #define RPI_FIRMWARE_SET_RTC_REG 0x00038087 +-enum {RTC_TIME, RTC_ALARM, RTC_ALARM_PENDING, RTC_ALARM_ENABLE}; ++ ++enum { ++ RTC_TIME, ++ RTC_ALARM, ++ RTC_ALARM_PENDING, ++ RTC_ALARM_ENABLE, ++ RTC_BBAT_CHG_VOLTS, ++ RTC_BBAT_CHG_VOLTS_MIN, ++ RTC_BBAT_CHG_VOLTS_MAX, ++ RTC_BBAT_VOLTS ++}; + + static int rpi_rtc_read_time(struct device *dev, struct rtc_time *tm) + { +@@ -114,6 +125,83 @@ static const struct rtc_class_ops rpi_rt + .alarm_irq_enable = rpi_rtc_alarm_irq_enable, + }; + ++static int rpi_rtc_set_charge_voltage(struct device *dev) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_BBAT_CHG_VOLTS, vrtc->bbat_vchg_microvolts}; ++ int err; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++ ++ if (err) ++ dev_err(dev, "failed to set trickle charge voltage to %uuV: %d\n", ++ vrtc->bbat_vchg_microvolts, err); ++ else if (vrtc->bbat_vchg_microvolts) ++ dev_info(dev, "trickle charging enabled at %uuV\n", ++ vrtc->bbat_vchg_microvolts); ++ ++ return err; ++} ++ ++static ssize_t rpi_rtc_print_uint_reg(struct device *dev, char *buf, u32 reg) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev->parent); ++ u32 data[2] = {reg, 0}; ++ int ret = 0; ++ ++ ret = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ if (ret < 0) ++ return ret; ++ ++ return sprintf(buf, "%u\n", data[1]); ++} ++ ++static ssize_t charging_voltage_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_CHG_VOLTS); ++} ++static DEVICE_ATTR_RO(charging_voltage); ++ ++static ssize_t charging_voltage_min_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_CHG_VOLTS_MIN); ++} ++static DEVICE_ATTR_RO(charging_voltage_min); ++ ++static ssize_t charging_voltage_max_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_CHG_VOLTS_MAX); ++} ++static DEVICE_ATTR_RO(charging_voltage_max); ++ ++static ssize_t battery_voltage_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_VOLTS); ++} ++static DEVICE_ATTR_RO(battery_voltage); ++ ++static struct attribute *rpi_rtc_attrs[] = { ++ &dev_attr_charging_voltage.attr, ++ &dev_attr_charging_voltage_min.attr, ++ &dev_attr_charging_voltage_max.attr, ++ &dev_attr_battery_voltage.attr, ++ NULL ++}; ++ ++static const struct attribute_group rpi_rtc_sysfs_files = { ++ .attrs = rpi_rtc_attrs, ++}; ++ + static int rpi_rtc_probe(struct platform_device *pdev) + { + struct rpi_rtc_data *vrtc; +@@ -151,10 +239,22 @@ static int rpi_rtc_probe(struct platform + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, vrtc->rtc->features); + + vrtc->rtc->ops = &rpi_rtc_ops; +- ret = devm_rtc_register_device(vrtc->rtc); ++ ret = rtc_add_group(vrtc->rtc, &rpi_rtc_sysfs_files); ++ if (ret) ++ return ret; + + rpi_rtc_alarm_clear_pending(dev); +- return ret; ++ ++ /* ++ * Optionally enable trickle charging - if the property isn't ++ * present (or set to zero), trickle charging is disabled. ++ */ ++ of_property_read_u32(np, "trickle-charge-microvolt", ++ &vrtc->bbat_vchg_microvolts); ++ ++ rpi_rtc_set_charge_voltage(dev); ++ ++ return devm_rtc_register_device(vrtc->rtc); + } + + static const struct of_device_id rpi_rtc_dt_match[] = { diff --git a/target/linux/bcm27xx/patches-6.1/950-0928-vc4_drv-Avoid-panic-when-booted-with-no-kms.patch b/target/linux/bcm27xx/patches-6.1/950-0928-vc4_drv-Avoid-panic-when-booted-with-no-kms.patch new file mode 100644 index 0000000000..8aae09c81a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0928-vc4_drv-Avoid-panic-when-booted-with-no-kms.patch @@ -0,0 +1,29 @@ +From 0f5fd4538774aa6c936bb8fc78611c3113bf19d7 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Mon, 17 Apr 2023 15:21:41 +0100 +Subject: [PATCH] vc4_drv: Avoid panic when booted with no kms + +If kms/fkms overlay is not present we have no matching drivers +and so match is NULL. + +It is not safe to call component_master_add_with_match with a null match argument. + +So don't do that + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_drv.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -456,6 +456,9 @@ static int vc4_platform_drm_probe(struct + vc4_match_add_drivers(dev, &match, + component_drivers, ARRAY_SIZE(component_drivers)); + ++ if (!match) ++ return -ENODEV; ++ + return component_master_add_with_match(dev, &vc4_drm_ops, match); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0929-drm-vc4-Treat-zero-sized-destination-as-full-screen.patch b/target/linux/bcm27xx/patches-6.1/950-0929-drm-vc4-Treat-zero-sized-destination-as-full-screen.patch new file mode 100644 index 0000000000..70a11df293 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0929-drm-vc4-Treat-zero-sized-destination-as-full-screen.patch @@ -0,0 +1,28 @@ +From 2c987545a88507acdd8a572a3bd23a4ca0124d14 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Thu, 13 Apr 2023 17:41:11 +0100 +Subject: [PATCH] drm/vc4: Treat zero sized destination as full screen + +Kodi video planes come through with all zeros for fullscreen +Without this check, we WARN when writing width-1, height-1 +to destination dlist + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_plane.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -484,6 +484,11 @@ static int vc4_plane_setup_clipping_and_ + vc4_state->crtc_w = state->dst.x2 - state->dst.x1; + vc4_state->crtc_h = state->dst.y2 - state->dst.y1; + ++ if (!vc4_state->crtc_w) ++ vc4_state->crtc_w = state->crtc->mode.hdisplay; ++ if (!vc4_state->crtc_h) ++ vc4_state->crtc_h = state->crtc->mode.vdisplay; ++ + ret = vc4_plane_margins_adj(state); + if (ret) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-0930-drm-vc4-Fix-FKMS-for-when-the-YUV-chroma-planes-are-.patch b/target/linux/bcm27xx/patches-6.1/950-0930-drm-vc4-Fix-FKMS-for-when-the-YUV-chroma-planes-are-.patch new file mode 100644 index 0000000000..9182194403 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0930-drm-vc4-Fix-FKMS-for-when-the-YUV-chroma-planes-are-.patch @@ -0,0 +1,50 @@ +From bb1ee75de382c7a5218750476aa2a5792309cc70 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 30 Mar 2023 17:18:36 +0100 +Subject: [PATCH] drm/vc4: Fix FKMS for when the YUV chroma planes are + different buffers + +The code was assuming that it was a single buffer with offsets, +when kmstest uses separate buffers and 0 offsets for each plane. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -528,7 +528,7 @@ static int vc4_plane_to_mb(struct drm_pl + struct drm_plane_state *state) + { + struct drm_framebuffer *fb = state->fb; +- struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); ++ struct drm_gem_dma_object *bo; + const struct drm_format_info *drm_fmt = fb->format; + const struct vc_image_format *vc_fmt = + vc4_get_vc_image_fmt(drm_fmt->format); +@@ -552,6 +552,7 @@ static int vc4_plane_to_mb(struct drm_pl + state->normalized_zpos : -127; + mb->plane.num_planes = num_planes; + mb->plane.is_vu = vc_fmt->is_vu; ++ bo = drm_fb_dma_get_gem_obj(fb, 0); + mb->plane.planes[0] = bo->dma_addr + fb->offsets[0]; + + rotation = drm_rotation_simplify(state->rotation, +@@ -572,11 +573,14 @@ static int vc4_plane_to_mb(struct drm_pl + /* Makes assumptions on the stride for the chroma planes as we + * can't easily plumb in non-standard pitches. + */ ++ bo = drm_fb_dma_get_gem_obj(fb, 1); + mb->plane.planes[1] = bo->dma_addr + fb->offsets[1]; +- if (num_planes > 2) ++ if (num_planes > 2) { ++ bo = drm_fb_dma_get_gem_obj(fb, 2); + mb->plane.planes[2] = bo->dma_addr + fb->offsets[2]; +- else ++ } else { + mb->plane.planes[2] = 0; ++ } + + /* Special case the YUV420 with U and V as line interleaved + * planes as we have special handling for that case. diff --git a/target/linux/bcm27xx/patches-6.1/950-0931-drm-vc4-hdmi-Enable-the-audio-clock.patch b/target/linux/bcm27xx/patches-6.1/950-0931-drm-vc4-hdmi-Enable-the-audio-clock.patch new file mode 100644 index 0000000000..f228dca9d5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0931-drm-vc4-hdmi-Enable-the-audio-clock.patch @@ -0,0 +1,39 @@ +From 0da58dfbd2cc2cfa14a629787b9ba6fa10b5f666 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 29 Mar 2023 15:26:52 +0100 +Subject: [PATCH] drm/vc4: hdmi: Enable the audio clock + +The audio clock is used by the HDMI controller driver and we were using +it to get its audio rate and compute the dividers needed to reach a +given audio sample rate. + +However, we were never enabling it, which was resulting in lockups on +the BCM2712. + +Fixes: 632ee3aa8786 ("drm/vc4: hdmi: Add audio-related callbacks") +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -3625,6 +3625,7 @@ static int vc4_hdmi_runtime_suspend(stru + { + struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + ++ clk_disable_unprepare(vc4_hdmi->audio_clock); + clk_disable_unprepare(vc4_hdmi->hsm_rpm_clock); + + return 0; +@@ -3666,6 +3667,10 @@ static int vc4_hdmi_runtime_resume(struc + goto err_disable_clk; + } + ++ ret = clk_prepare_enable(vc4_hdmi->audio_clock); ++ if (ret) ++ goto err_disable_clk; ++ + if (vc4_hdmi->variant->reset) + vc4_hdmi->variant->reset(vc4_hdmi); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0932-drm-vc4-hdmi-Warn-if-writing-to-an-unknown-HDMI-regi.patch b/target/linux/bcm27xx/patches-6.1/950-0932-drm-vc4-hdmi-Warn-if-writing-to-an-unknown-HDMI-regi.patch new file mode 100644 index 0000000000..fa6a399dae --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0932-drm-vc4-hdmi-Warn-if-writing-to-an-unknown-HDMI-regi.patch @@ -0,0 +1,31 @@ +From cdbebb3a92aca7327c88c6dc6ef5d4cd470d49fc Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 23 Feb 2023 19:44:32 +0100 +Subject: [PATCH] drm/vc4: hdmi: Warn if writing to an unknown HDMI register + +The VC4 HDMI driver has a bunch of accessors to read from a register. +The read accessor was warning when accessing an unknown register, but +the write one was just returning silently. + +Let's make sure we warn also when writing to an unknown register. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +@@ -498,8 +498,11 @@ static inline void vc4_hdmi_write(struct + + field = &variant->registers[reg]; + base = __vc4_hdmi_get_field_base(hdmi, field->reg); +- if (!base) ++ if (!base) { ++ dev_warn(&hdmi->pdev->dev, ++ "Unknown register ID %u\n", reg); + return; ++ } + + writel(value, base + field->offset); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0933-drm-vc4-hvs-More-logging-for-dlist-generation.patch b/target/linux/bcm27xx/patches-6.1/950-0933-drm-vc4-hvs-More-logging-for-dlist-generation.patch new file mode 100644 index 0000000000..dee2fc0d66 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0933-drm-vc4-hvs-More-logging-for-dlist-generation.patch @@ -0,0 +1,41 @@ +From 4ebd8283403daf5507e5aafb42fe3e4c7612eb14 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 22 Mar 2023 09:51:51 +0100 +Subject: [PATCH] drm/vc4: hvs: More logging for dlist generation + +DLIST generation can get pretty tricky and there's not a lot of debug in +the driver to help. Let's add a few more to track the generated DLIST +size. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -826,11 +826,22 @@ int vc4_hvs_atomic_check(struct drm_crtc + if (hweight32(crtc_state->connector_mask) > 1) + return -EINVAL; + +- drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) +- dlist_count += vc4_plane_dlist_size(plane_state); ++ drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { ++ u32 plane_dlist_count = vc4_plane_dlist_size(plane_state); ++ ++ drm_dbg_driver(dev, "[CRTC:%d:%s] Found [PLANE:%d:%s] with DLIST size: %u\n", ++ crtc->base.id, crtc->name, ++ plane->base.id, plane->name, ++ plane_dlist_count); ++ ++ dlist_count += plane_dlist_count; ++ } + + dlist_count++; /* Account for SCALER_CTL0_END. */ + ++ drm_dbg_driver(dev, "[CRTC:%d:%s] Allocating DLIST block with size: %u\n", ++ crtc->base.id, crtc->name, dlist_count); ++ + alloc = vc4_hvs_alloc_dlist_entry(vc4->hvs, vc4_state->assigned_channel, dlist_count); + if (IS_ERR(alloc)) + return PTR_ERR(alloc); diff --git a/target/linux/bcm27xx/patches-6.1/950-0934-drm-vc4-hvs-Print-error-if-we-fail-an-allocation.patch b/target/linux/bcm27xx/patches-6.1/950-0934-drm-vc4-hvs-Print-error-if-we-fail-an-allocation.patch new file mode 100644 index 0000000000..7c7bbb4822 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0934-drm-vc4-hvs-Print-error-if-we-fail-an-allocation.patch @@ -0,0 +1,66 @@ +From c0af63193bd307f281211e7fb32a02a52c2869b2 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 22 Mar 2023 09:53:17 +0100 +Subject: [PATCH] drm/vc4: hvs: Print error if we fail an allocation + +We need to allocate a few additional structures when checking our +atomic_state, especially related to hardware SRAM that will hold the +plane descriptors (DLIST) and the current line context (LBM) during +composition. + +Since those allocation can fail, let's add some error message in that +case to help debug what goes wrong. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 6 +++++- + drivers/gpu/drm/vc4/vc4_plane.c | 7 +++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -441,6 +441,8 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs + unsigned int channel, + size_t dlist_count) + { ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *dev = &vc4->base; + struct vc4_hvs_dlist_allocation *alloc; + unsigned long flags; + int ret; +@@ -458,8 +460,10 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs + ret = drm_mm_insert_node(&hvs->dlist_mm, &alloc->mm_node, + dlist_count); + spin_unlock_irqrestore(&hvs->mm_lock, flags); +- if (ret) ++ if (ret) { ++ drm_err(dev, "Failed to allocate DLIST entry: %d\n", ret); + return ERR_PTR(ret); ++ } + + alloc->channel = channel; + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -733,7 +733,8 @@ static void vc4_plane_calc_load(struct d + + static int vc4_plane_allocate_lbm(struct drm_plane_state *state) + { +- struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); ++ struct drm_device *drm = state->plane->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + unsigned long irqflags; + u32 lbm_size; +@@ -759,8 +760,10 @@ static int vc4_plane_allocate_lbm(struct + 0, 0); + spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); + +- if (ret) ++ if (ret) { ++ drm_err(drm, "Failed to allocate LBM entry: %d\n", ret); + return ret; ++ } + } else { + WARN_ON_ONCE(lbm_size != vc4_state->lbm.size); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0935-drm-vc4-plane-Add-more-debugging-for-LBM-allocation.patch b/target/linux/bcm27xx/patches-6.1/950-0935-drm-vc4-plane-Add-more-debugging-for-LBM-allocation.patch new file mode 100644 index 0000000000..d8d68e79aa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0935-drm-vc4-plane-Add-more-debugging-for-LBM-allocation.patch @@ -0,0 +1,36 @@ +From 164f7e94da446984f275be1c082b93243beadfba Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 22 Mar 2023 16:17:57 +0100 +Subject: [PATCH] drm/vc4: plane: Add more debugging for LBM allocation + +LBM allocations need a different size depending on the line length, +format, etc. + +This can get tricky, and fail. Let's add some more prints to ease the +debugging when it does. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_plane.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -735,6 +735,7 @@ static int vc4_plane_allocate_lbm(struct + { + struct drm_device *drm = state->plane->dev; + struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct drm_plane *plane = state->plane; + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + unsigned long irqflags; + u32 lbm_size; +@@ -743,6 +744,9 @@ static int vc4_plane_allocate_lbm(struct + if (!lbm_size) + return 0; + ++ drm_dbg_driver(drm, "[PLANE:%d:%s] LBM Allocation Size: %u\n", ++ plane->base.id, plane->name, lbm_size); ++ + if (WARN_ON(!vc4_state->lbm_offset)) + return -EINVAL; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0936-drm-vc4-plane-Use-return-variable-in-atomic_check.patch b/target/linux/bcm27xx/patches-6.1/950-0936-drm-vc4-plane-Use-return-variable-in-atomic_check.patch new file mode 100644 index 0000000000..220245c351 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0936-drm-vc4-plane-Use-return-variable-in-atomic_check.patch @@ -0,0 +1,31 @@ +From 950394a39f659746e5933cbc203a8bedef8246b7 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 14:26:44 +0100 +Subject: [PATCH] drm/vc4: plane: Use return variable in atomic_check + +The vc4_plane_atomic_check() directly returns the result of the final +function it calls. + +Using the already defined ret variable to check its content on error, +and a separate return 0 on success, makes it easier to extend. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_plane.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1378,7 +1378,11 @@ static int vc4_plane_atomic_check(struct + if (ret) + return ret; + +- return vc4_plane_allocate_lbm(new_plane_state); ++ ret = vc4_plane_allocate_lbm(new_plane_state); ++ if (ret) ++ return ret; ++ ++ return 0; + } + + static void vc4_plane_atomic_update(struct drm_plane *plane, diff --git a/target/linux/bcm27xx/patches-6.1/950-0937-drm-vc4-crtc-Move-assigned_channel-to-a-variable.patch b/target/linux/bcm27xx/patches-6.1/950-0937-drm-vc4-crtc-Move-assigned_channel-to-a-variable.patch new file mode 100644 index 0000000000..3476f548c4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0937-drm-vc4-crtc-Move-assigned_channel-to-a-variable.patch @@ -0,0 +1,47 @@ +From f3c6acc345113c57011f2b1c8421e6cf78f0bc30 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:39:13 +0100 +Subject: [PATCH] drm/vc4: crtc: Move assigned_channel to a variable + +We access multiple times the vc4_crtc_state->assigned_channel variable +in the vc4_crtc_get_scanout_position() function, so let's store it in a +local variable. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -104,6 +104,7 @@ static bool vc4_crtc_get_scanout_positio + struct vc4_hvs *hvs = vc4->hvs; + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); ++ unsigned int channel = vc4_crtc_state->assigned_channel; + unsigned int cob_size; + u32 val; + int fifo_lines; +@@ -120,7 +121,7 @@ static bool vc4_crtc_get_scanout_positio + * Read vertical scanline which is currently composed for our + * pixelvalve by the HVS, and also the scaler status. + */ +- val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel)); ++ val = HVS_READ(SCALER_DISPSTATX(channel)); + + /* Get optional system timestamp after query. */ + if (etime) +@@ -136,11 +137,11 @@ static bool vc4_crtc_get_scanout_positio + *vpos /= 2; + + /* Use hpos to correct for field offset in interlaced mode. */ +- if (vc4_hvs_get_fifo_frame_count(hvs, vc4_crtc_state->assigned_channel) % 2) ++ if (vc4_hvs_get_fifo_frame_count(hvs, channel) % 2) + *hpos += mode->crtc_htotal / 2; + } + +- cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel); ++ cob_size = vc4_crtc_get_cob_allocation(vc4, channel); + /* This is the offset we need for translating hvs -> pv scanout pos. */ + fifo_lines = cob_size / mode->crtc_hdisplay; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0938-drm-vc4-Introduce-generation-number-enum.patch b/target/linux/bcm27xx/patches-6.1/950-0938-drm-vc4-Introduce-generation-number-enum.patch new file mode 100644 index 0000000000..9314c797a0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0938-drm-vc4-Introduce-generation-number-enum.patch @@ -0,0 +1,1029 @@ +From fa2571d625bb53b642cd9f29a7cfc3434e1cf576 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:07:36 +0100 +Subject: [PATCH] drm/vc4: Introduce generation number enum + +With the introduction of the BCM2712 support, we will get yet another +generation of display engine to support. + +The binary check of whether it's VC5 or not thus doesn't work anymore, +especially since some parts of the driver will have changed with BCM2711, +and some others with BCM2712. + +Let's introduce an enum to store the generation the driver is running +on, which should provide more flexibility. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 12 +++--- + drivers/gpu/drm/vc4/vc4_bo.c | 28 ++++++------ + drivers/gpu/drm/vc4/vc4_crtc.c | 14 +++--- + drivers/gpu/drm/vc4/vc4_drv.c | 22 ++++++---- + drivers/gpu/drm/vc4/vc4_drv.h | 7 ++- + drivers/gpu/drm/vc4/vc4_gem.c | 24 +++++------ + drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- + drivers/gpu/drm/vc4/vc4_hvs.c | 50 ++++++++++++---------- + drivers/gpu/drm/vc4/vc4_irq.c | 10 ++--- + drivers/gpu/drm/vc4/vc4_kms.c | 14 +++--- + drivers/gpu/drm/vc4/vc4_perfmon.c | 20 ++++----- + drivers/gpu/drm/vc4/vc4_plane.c | 12 +++--- + drivers/gpu/drm/vc4/vc4_render_cl.c | 2 +- + drivers/gpu/drm/vc4/vc4_v3d.c | 10 ++--- + drivers/gpu/drm/vc4/vc4_validate.c | 8 ++-- + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 2 +- + 16 files changed, 126 insertions(+), 111 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -153,11 +153,11 @@ static int __build_mock(struct kunit *te + return 0; + } + +-static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5) ++static struct vc4_dev *__mock_device(struct kunit *test, enum vc4_gen gen) + { + struct drm_device *drm; +- const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver; +- const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock; ++ const struct drm_driver *drv = (gen == VC4_GEN_5) ? &vc5_drm_driver : &vc4_drm_driver; ++ const struct vc4_mock_desc *desc = (gen == VC4_GEN_5) ? &vc5_mock : &vc4_mock; + struct vc4_dev *vc4; + struct device *dev; + int ret; +@@ -171,7 +171,7 @@ static struct vc4_dev *__mock_device(str + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); + + vc4->dev = dev; +- vc4->is_vc5 = is_vc5; ++ vc4->gen = gen; + + vc4->hvs = __vc4_hvs_alloc(vc4, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs); +@@ -191,10 +191,10 @@ static struct vc4_dev *__mock_device(str + + struct vc4_dev *vc4_mock_device(struct kunit *test) + { +- return __mock_device(test, false); ++ return __mock_device(test, VC4_GEN_4); + } + + struct vc4_dev *vc5_mock_device(struct kunit *test) + { +- return __mock_device(test, true); ++ return __mock_device(test, VC4_GEN_5); + } +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -251,7 +251,7 @@ void vc4_bo_add_to_purgeable_pool(struct + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->purgeable.lock); +@@ -265,7 +265,7 @@ static void vc4_bo_remove_from_purgeable + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* list_del_init() is used here because the caller might release +@@ -396,7 +396,7 @@ struct drm_gem_object *vc4_create_object + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); +@@ -427,7 +427,7 @@ struct vc4_bo *vc4_bo_create(struct drm_ + struct drm_gem_dma_object *dma_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + if (size == 0) +@@ -496,7 +496,7 @@ int vc4_bo_dumb_create(struct drm_file * + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + ret = vc4_dumb_fixup_args(args); +@@ -622,7 +622,7 @@ int vc4_bo_inc_usecnt(struct vc4_bo *bo) + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* Fast path: if the BO is already retained by someone, no need to +@@ -661,7 +661,7 @@ void vc4_bo_dec_usecnt(struct vc4_bo *bo + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* Fast path: if the BO is still retained by someone, no need to test +@@ -783,7 +783,7 @@ int vc4_create_bo_ioctl(struct drm_devic + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + ret = vc4_grab_bin_bo(vc4, vc4file); +@@ -813,7 +813,7 @@ int vc4_mmap_bo_ioctl(struct drm_device + struct drm_vc4_mmap_bo *args = data; + struct drm_gem_object *gem_obj; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + gem_obj = drm_gem_object_lookup(file_priv, args->handle); +@@ -839,7 +839,7 @@ vc4_create_shader_bo_ioctl(struct drm_de + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->size == 0) +@@ -918,7 +918,7 @@ int vc4_set_tiling_ioctl(struct drm_devi + struct vc4_bo *bo; + bool t_format; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->flags != 0) +@@ -964,7 +964,7 @@ int vc4_get_tiling_ioctl(struct drm_devi + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->flags != 0 || args->modifier != 0) +@@ -1011,7 +1011,7 @@ int vc4_bo_cache_init(struct drm_device + int ret; + int i; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* Create the initial set of BO labels that the kernel will +@@ -1075,7 +1075,7 @@ int vc4_label_bo_ioctl(struct drm_device + struct drm_gem_object *gem_obj; + int ret = 0, label; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!args->len) +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -263,7 +263,7 @@ static u32 vc4_get_fifo_full_level(struc + * Removing 1 from the FIFO full level however + * seems to completely remove that issue. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1; + + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX; +@@ -445,7 +445,7 @@ static void vc4_crtc_config_pv(struct dr + if (is_dsi) + CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + CRTC_WRITE(PV_MUX_CFG, + VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP, + PV_MUX_CFG_RGB_PIXEL_MUX_MODE)); +@@ -936,7 +936,7 @@ static int vc4_async_set_fence_cb(struct + struct dma_fence *fence; + int ret; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + + return vc4_queue_seqno_cb(dev, &flip_state->cb.seqno, bo->seqno, +@@ -1023,7 +1023,7 @@ static int vc4_async_page_flip(struct dr + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* +@@ -1066,7 +1066,7 @@ int vc4_page_flip(struct drm_crtc *crtc, + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + return vc5_async_page_flip(crtc, fb, event, flags); + else + return vc4_async_page_flip(crtc, fb, event, flags); +@@ -1358,13 +1358,13 @@ int __vc4_crtc_init(struct drm_device *d + + drm_crtc_helper_add(crtc, crtc_helper_funcs); + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); + drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); + } + + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* We support CTM, but only for one CRTC at a time. It's therefore + * implemented as private driver state in vc4_kms, not here. + */ +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -98,7 +98,7 @@ static int vc4_get_param_ioctl(struct dr + if (args->pad != 0) + return -EINVAL; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) +@@ -147,7 +147,7 @@ static int vc4_open(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + vc4file = kzalloc(sizeof(*vc4file), GFP_KERNEL); +@@ -165,7 +165,7 @@ static void vc4_close(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file = file->driver_priv; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (vc4file->bin_bo_used) +@@ -305,13 +305,17 @@ static int vc4_drm_bind(struct device *d + struct vc4_dev *vc4; + struct device_node *node; + struct drm_crtc *crtc; +- bool is_vc5; ++ enum vc4_gen gen; + int ret = 0; + + dev->coherent_dma_mask = DMA_BIT_MASK(32); + +- is_vc5 = of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5"); +- if (is_vc5) ++ if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) ++ gen = VC4_GEN_5; ++ else ++ gen = VC4_GEN_4; ++ ++ if (gen == VC4_GEN_5) + driver = &vc5_drm_driver; + else + driver = &vc4_drm_driver; +@@ -329,14 +333,14 @@ static int vc4_drm_bind(struct device *d + vc4 = devm_drm_dev_alloc(dev, driver, struct vc4_dev, base); + if (IS_ERR(vc4)) + return PTR_ERR(vc4); +- vc4->is_vc5 = is_vc5; ++ vc4->gen = gen; + vc4->dev = dev; + + drm = &vc4->base; + platform_set_drvdata(pdev, drm); + INIT_LIST_HEAD(&vc4->debugfs_list); + +- if (!is_vc5) { ++ if (gen == VC4_GEN_4) { + ret = drmm_mutex_init(drm, &vc4->bin_bo_lock); + if (ret) + return ret; +@@ -350,7 +354,7 @@ static int vc4_drm_bind(struct device *d + if (ret) + return ret; + +- if (!is_vc5) { ++ if (gen == VC4_GEN_4) { + ret = vc4_gem_init(drm); + if (ret) + return ret; +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -80,11 +80,16 @@ struct vc4_perfmon { + u64 counters[]; + }; + ++enum vc4_gen { ++ VC4_GEN_4, ++ VC4_GEN_5, ++}; ++ + struct vc4_dev { + struct drm_device base; + struct device *dev; + +- bool is_vc5; ++ enum vc4_gen gen; + + unsigned int irq; + +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -76,7 +76,7 @@ vc4_get_hang_state_ioctl(struct drm_devi + u32 i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -389,7 +389,7 @@ vc4_wait_for_seqno(struct drm_device *de + unsigned long timeout_expire; + DEFINE_WAIT(wait); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (vc4->finished_seqno >= seqno) +@@ -474,7 +474,7 @@ vc4_submit_next_bin_job(struct drm_devic + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + again: +@@ -522,7 +522,7 @@ vc4_submit_next_render_job(struct drm_de + if (!exec) + return; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* A previous RCL may have written to one of our textures, and +@@ -543,7 +543,7 @@ vc4_move_job_to_render(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + bool was_empty = list_empty(&vc4->render_job_list); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + list_move_tail(&exec->head, &vc4->render_job_list); +@@ -1012,7 +1012,7 @@ vc4_job_handle_completed(struct vc4_dev + unsigned long irqflags; + struct vc4_seqno_cb *cb, *cb_temp; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + spin_lock_irqsave(&vc4->job_lock, irqflags); +@@ -1051,7 +1051,7 @@ int vc4_queue_seqno_cb(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + cb->func = func; +@@ -1107,7 +1107,7 @@ vc4_wait_seqno_ioctl(struct drm_device * + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_vc4_wait_seqno *args = data; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno, +@@ -1124,7 +1124,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->pad != 0) +@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d + args->shader_rec_size, + args->bo_handle_count); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -1310,7 +1310,7 @@ int vc4_gem_init(struct drm_device *dev) + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + vc4->dma_fence_context = dma_fence_context_alloc(1); +@@ -1369,7 +1369,7 @@ int vc4_gem_madvise_ioctl(struct drm_dev + struct vc4_bo *bo; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + switch (args->madv) { +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -2614,7 +2614,7 @@ static int vc4_hdmi_audio_prepare(struct + VC4_HDMI_AUDIO_PACKET_CEA_MASK); + + /* Set the MAI threshold */ +- if (vc4->is_vc5) ++ if (vc4->gen >= VC4_GEN_5) + HDMI_WRITE(HDMI_MAI_THR, + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -416,7 +416,7 @@ static void vc4_hvs_irq_enable_eof(const + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->is_vc5 ? ++ u32 irq_mask = vc4->gen == VC4_GEN_5 ? + SCALER5_DISPCTRL_DSPEIEOF(channel) : + SCALER_DISPCTRL_DSPEIEOF(channel); + +@@ -428,7 +428,7 @@ static void vc4_hvs_irq_clear_eof(const + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->is_vc5 ? ++ u32 irq_mask = vc4->gen == VC4_GEN_5 ? + SCALER5_DISPCTRL_DSPEIEOF(channel) : + SCALER_DISPCTRL_DSPEIEOF(channel); + +@@ -620,7 +620,7 @@ int vc4_hvs_get_fifo_from_output(struct + u32 reg; + int ret; + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return output; + + /* +@@ -701,7 +701,7 @@ static int vc4_hvs_init_channel(struct v + dispctrl = SCALER_DISPCTRLX_ENABLE; + dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan)); + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + dispctrl |= VC4_SET_FIELD(mode->hdisplay, + SCALER_DISPCTRLX_WIDTH) | + VC4_SET_FIELD(mode->vdisplay, +@@ -732,7 +732,7 @@ static int vc4_hvs_init_channel(struct v + /* Reload the LUT, since the SRAMs would have been disabled if + * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + vc4_hvs_lut_load(hvs, vc4_crtc); + else + vc5_hvs_lut_load(hvs, vc4_crtc); +@@ -782,7 +782,7 @@ static int vc4_hvs_gamma_check(struct dr + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return 0; + + if (!crtc_state->color_mgmt_changed) +@@ -1036,7 +1036,7 @@ void vc4_hvs_atomic_flush(struct drm_crt + u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(channel)); + + if (crtc->state->gamma_lut) { +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + vc4_hvs_update_gamma_lut(hvs, vc4_crtc); + dispbkgndx |= SCALER_DISPBKGND_GAMMA; + } else { +@@ -1053,7 +1053,7 @@ void vc4_hvs_atomic_flush(struct drm_crt + * should already be disabling/enabling the pipeline + * when gamma changes. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; + } + HVS_WRITE(SCALER_DISPBKGNDX(channel), dispbkgndx); +@@ -1069,7 +1069,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + + void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u32 dispctrl; + int idx; + +@@ -1077,8 +1078,9 @@ void vc4_hvs_mask_underrun(struct vc4_hv + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- dispctrl &= ~(hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel)); ++ dispctrl &= ~((vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel)); + + HVS_WRITE(SCALER_DISPCTRL, dispctrl); + +@@ -1087,7 +1089,8 @@ void vc4_hvs_mask_underrun(struct vc4_hv + + void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u32 dispctrl; + int idx; + +@@ -1095,8 +1098,9 @@ void vc4_hvs_unmask_underrun(struct vc4_ + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- dispctrl |= (hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel)); ++ dispctrl |= ((vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel)); + + HVS_WRITE(SCALER_DISPSTAT, + SCALER_DISPSTAT_EUFLOW(channel)); +@@ -1139,8 +1143,10 @@ static irqreturn_t vc4_hvs_irq_handler(i + control = HVS_READ(SCALER_DISPCTRL); + + for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) { +- dspeislur = vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel); ++ dspeislur = (vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel); ++ + /* Interrupt masking is not always honored, so check it here. */ + if (status & SCALER_DISPSTAT_EUFLOW(channel) && + control & dspeislur) { +@@ -1177,7 +1183,7 @@ int vc4_hvs_debugfs_init(struct drm_mino + if (!vc4->hvs) + return -ENODEV; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, + minor->debugfs_root, + &vc4->load_tracker_enabled); +@@ -1235,7 +1241,7 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + * between planes when they don't overlap on the screen, but + * for now we just allocate globally. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + /* 48k words of 2x12-bit pixels */ + drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024); + else +@@ -1269,7 +1275,7 @@ static int vc4_hvs_bind(struct device *d + hvs->regset.regs = hvs_regs; + hvs->regset.nregs = ARRAY_SIZE(hvs_regs); + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + struct rpi_firmware *firmware; + struct device_node *node; + unsigned int max_rate; +@@ -1307,7 +1313,7 @@ static int vc4_hvs_bind(struct device *d + } + } + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + hvs->dlist = hvs->regs + SCALER_DLIST_START; + else + hvs->dlist = hvs->regs + SCALER5_DLIST_START; +@@ -1348,7 +1354,7 @@ static int vc4_hvs_bind(struct device *d + SCALER_DISPCTRL_DISPEIRQ(1) | + SCALER_DISPCTRL_DISPEIRQ(2); + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ | + SCALER_DISPCTRL_SLVWREIRQ | + SCALER_DISPCTRL_SLVRDEIRQ | +@@ -1403,7 +1409,7 @@ static int vc4_hvs_bind(struct device *d + + /* Recompute Composite Output Buffer (COB) allocations for the displays + */ +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* The COB is 20736 pixels, or just over 10 lines at 2048 wide. + * The bottom 2048 pixels are full 32bpp RGBA (intended for the + * TXP composing RGBA to memory), whilst the remainder are only +--- a/drivers/gpu/drm/vc4/vc4_irq.c ++++ b/drivers/gpu/drm/vc4/vc4_irq.c +@@ -265,7 +265,7 @@ vc4_irq_enable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (!vc4->v3d) +@@ -282,7 +282,7 @@ vc4_irq_disable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (!vc4->v3d) +@@ -305,7 +305,7 @@ int vc4_irq_install(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (irq == IRQ_NOTCONNECTED) +@@ -326,7 +326,7 @@ void vc4_irq_uninstall(struct drm_device + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + vc4_irq_disable(dev); +@@ -339,7 +339,7 @@ void vc4_irq_reset(struct drm_device *de + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* Acknowledge any stale IRQs. */ +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -378,7 +378,7 @@ static void vc4_atomic_commit_tail(struc + old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + +- if (vc4->is_vc5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long state_rate = max(old_hvs_state->core_clock_rate, + new_hvs_state->core_clock_rate); + unsigned long core_rate = clamp_t(unsigned long, state_rate, +@@ -398,7 +398,7 @@ static void vc4_atomic_commit_tail(struc + vc4_ctm_commit(vc4, state); + + if (!vc4->firmware_kms) { +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + vc5_hvs_pv_muxing_commit(vc4, state); + else + vc4_hvs_pv_muxing_commit(vc4, state); +@@ -417,7 +417,7 @@ static void vc4_atomic_commit_tail(struc + + drm_atomic_helper_cleanup_planes(dev, state); + +- if (vc4->is_vc5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long core_rate = min_t(unsigned long, + hvs->max_core_rate, + new_hvs_state->core_clock_rate); +@@ -482,7 +482,7 @@ static struct drm_framebuffer *vc4_fb_cr + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_mode_fb_cmd2 mode_cmd_local; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + /* If the user didn't specify a modifier, use the +@@ -1065,7 +1065,7 @@ int vc4_kms_load(struct drm_device *dev) + * the BCM2711, but the load tracker computations are used for + * the core clock rate calculation. + */ +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* Start with the load tracker enabled. Can be + * disabled through the debugfs load_tracker file. + */ +@@ -1081,7 +1081,7 @@ int vc4_kms_load(struct drm_device *dev) + return ret; + } + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + dev->mode_config.max_width = 7680; + dev->mode_config.max_height = 7680; + } else { +@@ -1089,7 +1089,7 @@ int vc4_kms_load(struct drm_device *dev) + dev->mode_config.max_height = 2048; + } + +- dev->mode_config.funcs = vc4->is_vc5 ? &vc5_mode_funcs : &vc4_mode_funcs; ++ dev->mode_config.funcs = (vc4->gen > VC4_GEN_4) ? &vc5_mode_funcs : &vc4_mode_funcs; + dev->mode_config.helper_private = &vc4_mode_config_helpers; + dev->mode_config.preferred_depth = 24; + dev->mode_config.async_page_flip = true; +--- a/drivers/gpu/drm/vc4/vc4_perfmon.c ++++ b/drivers/gpu/drm/vc4/vc4_perfmon.c +@@ -23,7 +23,7 @@ void vc4_perfmon_get(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + refcount_inc(&perfmon->refcnt); +@@ -37,7 +37,7 @@ void vc4_perfmon_put(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (refcount_dec_and_test(&perfmon->refcnt)) +@@ -49,7 +49,7 @@ void vc4_perfmon_start(struct vc4_dev *v + unsigned int i; + u32 mask; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (WARN_ON_ONCE(!perfmon || vc4->active_perfmon)) +@@ -69,7 +69,7 @@ void vc4_perfmon_stop(struct vc4_dev *vc + { + unsigned int i; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (WARN_ON_ONCE(!vc4->active_perfmon || +@@ -90,7 +90,7 @@ struct vc4_perfmon *vc4_perfmon_find(str + struct vc4_dev *vc4 = vc4file->dev; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + mutex_lock(&vc4file->perfmon.lock); +@@ -105,7 +105,7 @@ void vc4_perfmon_open_file(struct vc4_fi + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_init(&vc4file->perfmon.lock); +@@ -126,7 +126,7 @@ void vc4_perfmon_close_file(struct vc4_f + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4file->perfmon.lock); +@@ -146,7 +146,7 @@ int vc4_perfmon_create_ioctl(struct drm_ + unsigned int i; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -200,7 +200,7 @@ int vc4_perfmon_destroy_ioctl(struct drm + struct drm_vc4_perfmon_destroy *req = data; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -228,7 +228,7 @@ int vc4_perfmon_get_values_ioctl(struct + struct vc4_perfmon *perfmon; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -633,10 +633,10 @@ static u32 vc4_lbm_size(struct drm_plane + } + + /* Align it to 64 or 128 (hvs5) bytes */ +- lbm = roundup(lbm, vc4->is_vc5 ? 128 : 64); ++ lbm = roundup(lbm, vc4->gen == VC4_GEN_5 ? 128 : 64); + + /* Each "word" of the LBM memory contains 2 or 4 (hvs5) pixels */ +- lbm /= vc4->is_vc5 ? 4 : 2; ++ lbm /= vc4->gen == VC4_GEN_5 ? 4 : 2; + + return lbm; + } +@@ -760,7 +760,7 @@ static int vc4_plane_allocate_lbm(struct + ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, + &vc4_state->lbm, + lbm_size, +- vc4->is_vc5 ? 64 : 32, ++ vc4->gen == VC4_GEN_5 ? 64 : 32, + 0, 0); + spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); + +@@ -1141,7 +1141,7 @@ static int vc4_plane_mode_set(struct drm + mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && + fb->format->has_alpha; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* Control word */ + vc4_dlist_write(vc4_state, + SCALER_CTL0_VALID | +@@ -1717,7 +1717,7 @@ struct drm_plane *vc4_plane_init(struct + }; + + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { +- if (!hvs_formats[i].hvs5_only || vc4->is_vc5) { ++ if (!hvs_formats[i].hvs5_only || vc4->gen == VC4_GEN_5) { + formats[num_formats] = hvs_formats[i].drm; + num_formats++; + } +@@ -1732,7 +1732,7 @@ struct drm_plane *vc4_plane_init(struct + return ERR_CAST(vc4_plane); + plane = &vc4_plane->base; + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + drm_plane_helper_add(plane, &vc5_plane_helper_funcs); + else + drm_plane_helper_add(plane, &vc4_plane_helper_funcs); +--- a/drivers/gpu/drm/vc4/vc4_render_cl.c ++++ b/drivers/gpu/drm/vc4/vc4_render_cl.c +@@ -599,7 +599,7 @@ int vc4_get_rcl(struct drm_device *dev, + bool has_bin = args->bin_cl_size != 0; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->min_x_tile > args->max_x_tile || +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -127,7 +127,7 @@ static int vc4_v3d_debugfs_ident(struct + int + vc4_v3d_pm_get(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + mutex_lock(&vc4->power_lock); +@@ -148,7 +148,7 @@ vc4_v3d_pm_get(struct vc4_dev *vc4) + void + vc4_v3d_pm_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->power_lock); +@@ -178,7 +178,7 @@ int vc4_v3d_get_bin_slot(struct vc4_dev + uint64_t seqno = 0; + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + try_again: +@@ -325,7 +325,7 @@ int vc4_v3d_bin_bo_get(struct vc4_dev *v + { + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + mutex_lock(&vc4->bin_bo_lock); +@@ -360,7 +360,7 @@ static void bin_bo_release(struct kref * + + void vc4_v3d_bin_bo_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->bin_bo_lock); +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -109,7 +109,7 @@ vc4_use_bo(struct vc4_exec_info *exec, u + struct drm_gem_dma_object *obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + if (hindex >= exec->bo_count) { +@@ -169,7 +169,7 @@ vc4_check_tex_size(struct vc4_exec_info + uint32_t utile_w = utile_width(cpp); + uint32_t utile_h = utile_height(cpp); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return false; + + /* The shaded vertex format stores signed 12.4 fixed point +@@ -495,7 +495,7 @@ vc4_validate_bin_cl(struct drm_device *d + uint32_t dst_offset = 0; + uint32_t src_offset = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + while (src_offset < len) { +@@ -942,7 +942,7 @@ vc4_validate_shader_recs(struct drm_devi + uint32_t i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + for (i = 0; i < exec->shader_state_count; i++) { +--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c ++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +@@ -786,7 +786,7 @@ vc4_validate_shader(struct drm_gem_dma_o + struct vc4_validated_shader_info *validated_shader = NULL; + struct vc4_shader_validation_state validation_state; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + memset(&validation_state, 0, sizeof(validation_state)); diff --git a/target/linux/bcm27xx/patches-6.1/950-0939-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch b/target/linux/bcm27xx/patches-6.1/950-0939-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch new file mode 100644 index 0000000000..699db05e0c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0939-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch @@ -0,0 +1,577 @@ +From c382ea6b0457027b6ad883ee4348e03df515a785 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:29:27 +0100 +Subject: [PATCH] drm/vc4: Make v3d paths unavailable on any generation newer + than vc4 + +The V3D IP has been separate since BCM2711, so let's make sure we issue +a WARN if we're running not only on BCM2711, but also anything newer. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_bo.c | 28 +++++++++++----------- + drivers/gpu/drm/vc4/vc4_crtc.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_drv.c | 8 +++---- + drivers/gpu/drm/vc4/vc4_gem.c | 24 +++++++++---------- + drivers/gpu/drm/vc4/vc4_irq.c | 10 ++++---- + drivers/gpu/drm/vc4/vc4_kms.c | 2 +- + drivers/gpu/drm/vc4/vc4_perfmon.c | 20 ++++++++-------- + drivers/gpu/drm/vc4/vc4_render_cl.c | 2 +- + drivers/gpu/drm/vc4/vc4_v3d.c | 10 ++++---- + drivers/gpu/drm/vc4/vc4_validate.c | 8 +++---- + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 2 +- + 11 files changed, 59 insertions(+), 59 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -251,7 +251,7 @@ void vc4_bo_add_to_purgeable_pool(struct + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4->purgeable.lock); +@@ -265,7 +265,7 @@ static void vc4_bo_remove_from_purgeable + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* list_del_init() is used here because the caller might release +@@ -396,7 +396,7 @@ struct drm_gem_object *vc4_create_object + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return ERR_PTR(-ENODEV); + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); +@@ -427,7 +427,7 @@ struct vc4_bo *vc4_bo_create(struct drm_ + struct drm_gem_dma_object *dma_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return ERR_PTR(-ENODEV); + + if (size == 0) +@@ -496,7 +496,7 @@ int vc4_bo_dumb_create(struct drm_file * + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + ret = vc4_dumb_fixup_args(args); +@@ -622,7 +622,7 @@ int vc4_bo_inc_usecnt(struct vc4_bo *bo) + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + /* Fast path: if the BO is already retained by someone, no need to +@@ -661,7 +661,7 @@ void vc4_bo_dec_usecnt(struct vc4_bo *bo + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* Fast path: if the BO is still retained by someone, no need to test +@@ -783,7 +783,7 @@ int vc4_create_bo_ioctl(struct drm_devic + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + ret = vc4_grab_bin_bo(vc4, vc4file); +@@ -813,7 +813,7 @@ int vc4_mmap_bo_ioctl(struct drm_device + struct drm_vc4_mmap_bo *args = data; + struct drm_gem_object *gem_obj; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + gem_obj = drm_gem_object_lookup(file_priv, args->handle); +@@ -839,7 +839,7 @@ vc4_create_shader_bo_ioctl(struct drm_de + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->size == 0) +@@ -918,7 +918,7 @@ int vc4_set_tiling_ioctl(struct drm_devi + struct vc4_bo *bo; + bool t_format; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->flags != 0) +@@ -964,7 +964,7 @@ int vc4_get_tiling_ioctl(struct drm_devi + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->flags != 0 || args->modifier != 0) +@@ -1011,7 +1011,7 @@ int vc4_bo_cache_init(struct drm_device + int ret; + int i; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + /* Create the initial set of BO labels that the kernel will +@@ -1075,7 +1075,7 @@ int vc4_label_bo_ioctl(struct drm_device + struct drm_gem_object *gem_obj; + int ret = 0, label; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!args->len) +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -1023,7 +1023,7 @@ static int vc4_async_page_flip(struct dr + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + /* +@@ -1066,7 +1066,7 @@ int vc4_page_flip(struct drm_crtc *crtc, + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (vc4->gen == VC4_GEN_5) ++ if (vc4->gen > VC4_GEN_4) + return vc5_async_page_flip(crtc, fb, event, flags); + else + return vc4_async_page_flip(crtc, fb, event, flags); +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -98,7 +98,7 @@ static int vc4_get_param_ioctl(struct dr + if (args->pad != 0) + return -EINVAL; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) +@@ -147,7 +147,7 @@ static int vc4_open(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + vc4file = kzalloc(sizeof(*vc4file), GFP_KERNEL); +@@ -165,7 +165,7 @@ static void vc4_close(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file = file->driver_priv; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (vc4file->bin_bo_used) +@@ -315,7 +315,7 @@ static int vc4_drm_bind(struct device *d + else + gen = VC4_GEN_4; + +- if (gen == VC4_GEN_5) ++ if (gen > VC4_GEN_4) + driver = &vc5_drm_driver; + else + driver = &vc4_drm_driver; +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -76,7 +76,7 @@ vc4_get_hang_state_ioctl(struct drm_devi + u32 i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -389,7 +389,7 @@ vc4_wait_for_seqno(struct drm_device *de + unsigned long timeout_expire; + DEFINE_WAIT(wait); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (vc4->finished_seqno >= seqno) +@@ -474,7 +474,7 @@ vc4_submit_next_bin_job(struct drm_devic + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + again: +@@ -522,7 +522,7 @@ vc4_submit_next_render_job(struct drm_de + if (!exec) + return; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* A previous RCL may have written to one of our textures, and +@@ -543,7 +543,7 @@ vc4_move_job_to_render(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + bool was_empty = list_empty(&vc4->render_job_list); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + list_move_tail(&exec->head, &vc4->render_job_list); +@@ -1012,7 +1012,7 @@ vc4_job_handle_completed(struct vc4_dev + unsigned long irqflags; + struct vc4_seqno_cb *cb, *cb_temp; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + spin_lock_irqsave(&vc4->job_lock, irqflags); +@@ -1051,7 +1051,7 @@ int vc4_queue_seqno_cb(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + cb->func = func; +@@ -1107,7 +1107,7 @@ vc4_wait_seqno_ioctl(struct drm_device * + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_vc4_wait_seqno *args = data; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno, +@@ -1124,7 +1124,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->pad != 0) +@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d + args->shader_rec_size, + args->bo_handle_count); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -1310,7 +1310,7 @@ int vc4_gem_init(struct drm_device *dev) + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + vc4->dma_fence_context = dma_fence_context_alloc(1); +@@ -1369,7 +1369,7 @@ int vc4_gem_madvise_ioctl(struct drm_dev + struct vc4_bo *bo; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + switch (args->madv) { +--- a/drivers/gpu/drm/vc4/vc4_irq.c ++++ b/drivers/gpu/drm/vc4/vc4_irq.c +@@ -265,7 +265,7 @@ vc4_irq_enable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (!vc4->v3d) +@@ -282,7 +282,7 @@ vc4_irq_disable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (!vc4->v3d) +@@ -305,7 +305,7 @@ int vc4_irq_install(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (irq == IRQ_NOTCONNECTED) +@@ -326,7 +326,7 @@ void vc4_irq_uninstall(struct drm_device + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + vc4_irq_disable(dev); +@@ -339,7 +339,7 @@ void vc4_irq_reset(struct drm_device *de + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* Acknowledge any stale IRQs. */ +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -482,7 +482,7 @@ static struct drm_framebuffer *vc4_fb_cr + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_mode_fb_cmd2 mode_cmd_local; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return ERR_PTR(-ENODEV); + + /* If the user didn't specify a modifier, use the +--- a/drivers/gpu/drm/vc4/vc4_perfmon.c ++++ b/drivers/gpu/drm/vc4/vc4_perfmon.c +@@ -23,7 +23,7 @@ void vc4_perfmon_get(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + refcount_inc(&perfmon->refcnt); +@@ -37,7 +37,7 @@ void vc4_perfmon_put(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (refcount_dec_and_test(&perfmon->refcnt)) +@@ -49,7 +49,7 @@ void vc4_perfmon_start(struct vc4_dev *v + unsigned int i; + u32 mask; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (WARN_ON_ONCE(!perfmon || vc4->active_perfmon)) +@@ -69,7 +69,7 @@ void vc4_perfmon_stop(struct vc4_dev *vc + { + unsigned int i; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (WARN_ON_ONCE(!vc4->active_perfmon || +@@ -90,7 +90,7 @@ struct vc4_perfmon *vc4_perfmon_find(str + struct vc4_dev *vc4 = vc4file->dev; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return NULL; + + mutex_lock(&vc4file->perfmon.lock); +@@ -105,7 +105,7 @@ void vc4_perfmon_open_file(struct vc4_fi + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_init(&vc4file->perfmon.lock); +@@ -126,7 +126,7 @@ void vc4_perfmon_close_file(struct vc4_f + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4file->perfmon.lock); +@@ -146,7 +146,7 @@ int vc4_perfmon_create_ioctl(struct drm_ + unsigned int i; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -200,7 +200,7 @@ int vc4_perfmon_destroy_ioctl(struct drm + struct drm_vc4_perfmon_destroy *req = data; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -228,7 +228,7 @@ int vc4_perfmon_get_values_ioctl(struct + struct vc4_perfmon *perfmon; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +--- a/drivers/gpu/drm/vc4/vc4_render_cl.c ++++ b/drivers/gpu/drm/vc4/vc4_render_cl.c +@@ -599,7 +599,7 @@ int vc4_get_rcl(struct drm_device *dev, + bool has_bin = args->bin_cl_size != 0; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->min_x_tile > args->max_x_tile || +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -127,7 +127,7 @@ static int vc4_v3d_debugfs_ident(struct + int + vc4_v3d_pm_get(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + mutex_lock(&vc4->power_lock); +@@ -148,7 +148,7 @@ vc4_v3d_pm_get(struct vc4_dev *vc4) + void + vc4_v3d_pm_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4->power_lock); +@@ -178,7 +178,7 @@ int vc4_v3d_get_bin_slot(struct vc4_dev + uint64_t seqno = 0; + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + try_again: +@@ -325,7 +325,7 @@ int vc4_v3d_bin_bo_get(struct vc4_dev *v + { + int ret = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + mutex_lock(&vc4->bin_bo_lock); +@@ -360,7 +360,7 @@ static void bin_bo_release(struct kref * + + void vc4_v3d_bin_bo_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4->bin_bo_lock); +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -109,7 +109,7 @@ vc4_use_bo(struct vc4_exec_info *exec, u + struct drm_gem_dma_object *obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return NULL; + + if (hindex >= exec->bo_count) { +@@ -169,7 +169,7 @@ vc4_check_tex_size(struct vc4_exec_info + uint32_t utile_w = utile_width(cpp); + uint32_t utile_h = utile_height(cpp); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return false; + + /* The shaded vertex format stores signed 12.4 fixed point +@@ -495,7 +495,7 @@ vc4_validate_bin_cl(struct drm_device *d + uint32_t dst_offset = 0; + uint32_t src_offset = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + while (src_offset < len) { +@@ -942,7 +942,7 @@ vc4_validate_shader_recs(struct drm_devi + uint32_t i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + for (i = 0; i < exec->shader_state_count; i++) { +--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c ++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +@@ -786,7 +786,7 @@ vc4_validate_shader(struct drm_gem_dma_o + struct vc4_validated_shader_info *validated_shader = NULL; + struct vc4_shader_validation_state validation_state; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return NULL; + + memset(&validation_state, 0, sizeof(validation_state)); diff --git a/target/linux/bcm27xx/patches-6.1/950-0940-drm-vc4-hvs-Use-switch-statement-to-simplify-vc4_hvs.patch b/target/linux/bcm27xx/patches-6.1/950-0940-drm-vc4-hvs-Use-switch-statement-to-simplify-vc4_hvs.patch new file mode 100644 index 0000000000..048b5d3222 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0940-drm-vc4-hvs-Use-switch-statement-to-simplify-vc4_hvs.patch @@ -0,0 +1,125 @@ +From 72e5eb3d9511af2f056911d70c4d033d4fc674b2 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:07:29 +0100 +Subject: [PATCH] drm/vc4: hvs: Use switch statement to simplify + vc4_hvs_get_fifo_from_output + +Since we'll support BCM2712 soon, let's move the logic behind +vc4_hvs_get_fifo_from_output() to a switch to extend it more easily. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 80 +++++++++++++++++++---------------- + 1 file changed, 43 insertions(+), 37 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -620,57 +620,63 @@ int vc4_hvs_get_fifo_from_output(struct + u32 reg; + int ret; + +- if (vc4->gen == VC4_GEN_4) ++ switch (vc4->gen) { ++ case VC4_GEN_4: + return output; + +- /* +- * NOTE: We should probably use drm_dev_enter()/drm_dev_exit() +- * here, but this function is only used during the DRM device +- * initialization, so we should be fine. +- */ +- +- switch (output) { +- case 0: +- return 0; +- +- case 1: +- return 1; +- +- case 2: +- reg = HVS_READ(SCALER_DISPECTRL); +- ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg); +- if (ret == 0) +- return 2; +- +- return 0; +- +- case 3: +- reg = HVS_READ(SCALER_DISPCTRL); +- ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg); +- if (ret == 3) +- return -EPIPE; +- +- return ret; +- +- case 4: +- reg = HVS_READ(SCALER_DISPEOLN); +- ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg); +- if (ret == 3) +- return -EPIPE; ++ case VC4_GEN_5: ++ /* ++ * NOTE: We should probably use ++ * drm_dev_enter()/drm_dev_exit() here, but this ++ * function is only used during the DRM device ++ * initialization, so we should be fine. ++ */ ++ ++ switch (output) { ++ case 0: ++ return 0; ++ ++ case 1: ++ return 1; ++ ++ case 2: ++ reg = HVS_READ(SCALER_DISPECTRL); ++ ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg); ++ if (ret == 0) ++ return 2; ++ ++ return 0; ++ ++ case 3: ++ reg = HVS_READ(SCALER_DISPCTRL); ++ ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg); ++ if (ret == 3) ++ return -EPIPE; ++ ++ return ret; ++ ++ case 4: ++ reg = HVS_READ(SCALER_DISPEOLN); ++ ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg); ++ if (ret == 3) ++ return -EPIPE; ++ ++ return ret; ++ ++ case 5: ++ reg = HVS_READ(SCALER_DISPDITHER); ++ ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg); ++ if (ret == 3) ++ return -EPIPE; + +- return ret; ++ return ret; + +- case 5: +- reg = HVS_READ(SCALER_DISPDITHER); +- ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg); +- if (ret == 3) ++ default: + return -EPIPE; +- +- return ret; +- +- default: +- return -EPIPE; ++ } + } ++ ++ return -EPIPE; + } + + static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, diff --git a/target/linux/bcm27xx/patches-6.1/950-0941-drm-vc4-hvs-Use-switch-statement-to-simplify-enablin.patch b/target/linux/bcm27xx/patches-6.1/950-0941-drm-vc4-hvs-Use-switch-statement-to-simplify-enablin.patch new file mode 100644 index 0000000000..984b329fb4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0941-drm-vc4-hvs-Use-switch-statement-to-simplify-enablin.patch @@ -0,0 +1,74 @@ +From 72bfb10c9393688d00e4e0b00d416e23c2753318 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:07:29 +0100 +Subject: [PATCH] drm/vc4: hvs: Use switch statement to simplify + enabling/disabling irq + +Since we'll support BCM2712 soon, let's move the logic to enable and +disable the end-of-frame interrupts to a switch to extend it more +easily. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 42 ++++++++++++++++++++++++++--------- + 1 file changed, 32 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -416,24 +416,46 @@ static void vc4_hvs_irq_enable_eof(const + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->gen == VC4_GEN_5 ? +- SCALER5_DISPCTRL_DSPEIEOF(channel) : +- SCALER_DISPCTRL_DSPEIEOF(channel); + +- HVS_WRITE(SCALER_DISPCTRL, +- HVS_READ(SCALER_DISPCTRL) | irq_mask); ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) | ++ SCALER_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ case VC4_GEN_5: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) | ++ SCALER5_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ default: ++ break; ++ } + } + + static void vc4_hvs_irq_clear_eof(const struct vc4_hvs *hvs, + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->gen == VC4_GEN_5 ? +- SCALER5_DISPCTRL_DSPEIEOF(channel) : +- SCALER_DISPCTRL_DSPEIEOF(channel); + +- HVS_WRITE(SCALER_DISPCTRL, +- HVS_READ(SCALER_DISPCTRL) & ~irq_mask); ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) & ++ ~SCALER_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ case VC4_GEN_5: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) & ++ ~SCALER5_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ default: ++ break; ++ } + } + + static struct vc4_hvs_dlist_allocation * diff --git a/target/linux/bcm27xx/patches-6.1/950-0942-drm-vc4-hvs-Test-if-the-EOF-interrupts-are-enabled.patch b/target/linux/bcm27xx/patches-6.1/950-0942-drm-vc4-hvs-Test-if-the-EOF-interrupts-are-enabled.patch new file mode 100644 index 0000000000..704468b90e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0942-drm-vc4-hvs-Test-if-the-EOF-interrupts-are-enabled.patch @@ -0,0 +1,100 @@ +From bcf02f6ac0d429a425e8409f140bd875a1feed2e Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 13:46:53 +0200 +Subject: [PATCH] drm/vc4: hvs: Test if the EOF interrupts are enabled + +We currently enable the EOF interrupts through the CRTC destroy_state +implementation. + +However, nothing guarantees that we can't call destroy_state multiple +times in a row, and therefore before the EOF interrupt even happens. + +This means we would enable the interrupt multiple times but disable it +only once. It wasn't an issue so far since the interrupts were only +enabled by setting a bit in a register, but with BCM2712 we will use an +external interrupt controller, with a refcounted interrupt. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 8 ++++++-- + drivers/gpu/drm/vc4/vc4_hvs.c | 14 ++++++++++++-- + 2 files changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -333,6 +333,8 @@ struct vc4_v3d { + struct debugfs_regset32 regset; + }; + ++#define HVS_NUM_CHANNELS 3 ++ + struct vc4_hvs { + struct vc4_dev *vc4; + struct platform_device *pdev; +@@ -341,6 +343,10 @@ struct vc4_hvs { + + struct clk *core_clk; + ++ struct { ++ unsigned int enabled: 1; ++ } eof_irq[HVS_NUM_CHANNELS]; ++ + unsigned long max_core_rate; + + /* Memory manager for CRTCs to allocate space in the display +@@ -373,8 +379,6 @@ struct vc4_hvs { + bool vc5_hdmi_enable_4096by2160; + }; + +-#define HVS_NUM_CHANNELS 3 +- + struct vc4_hvs_state { + struct drm_private_state base; + unsigned long core_clock_rate; +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -412,11 +412,14 @@ static void vc5_hvs_update_gamma_lut(str + vc5_hvs_lut_load(hvs, vc4_crtc); + } + +-static void vc4_hvs_irq_enable_eof(const struct vc4_hvs *hvs, ++static void vc4_hvs_irq_enable_eof(struct vc4_hvs *hvs, + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; + ++ if (hvs->eof_irq[channel].enabled) ++ return; ++ + switch (vc4->gen) { + case VC4_GEN_4: + HVS_WRITE(SCALER_DISPCTRL, +@@ -433,13 +436,18 @@ static void vc4_hvs_irq_enable_eof(const + default: + break; + } ++ ++ hvs->eof_irq[channel].enabled = true; + } + +-static void vc4_hvs_irq_clear_eof(const struct vc4_hvs *hvs, ++static void vc4_hvs_irq_clear_eof(struct vc4_hvs *hvs, + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; + ++ if (!hvs->eof_irq[channel].enabled) ++ return; ++ + switch (vc4->gen) { + case VC4_GEN_4: + HVS_WRITE(SCALER_DISPCTRL, +@@ -456,6 +464,8 @@ static void vc4_hvs_irq_clear_eof(const + default: + break; + } ++ ++ hvs->eof_irq[channel].enabled = false; + } + + static struct vc4_hvs_dlist_allocation * diff --git a/target/linux/bcm27xx/patches-6.1/950-0943-drm-vc4-hvs-Create-hw_init-function.patch b/target/linux/bcm27xx/patches-6.1/950-0943-drm-vc4-hvs-Create-hw_init-function.patch new file mode 100644 index 0000000000..5b748b5e94 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0943-drm-vc4-hvs-Create-hw_init-function.patch @@ -0,0 +1,188 @@ +From f3c84bb53107cef0009347d071c1a188ce24b8a3 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 14:36:28 +0100 +Subject: [PATCH] drm/vc4: hvs: Create hw_init function + +Since the BCM2712 will feature a significantly different HVS, let's move +the hardware initialisation part of our bind function into a separate +function. + +That way, it will be easier to extend in the future. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 155 ++++++++++++++++++---------------- + 1 file changed, 83 insertions(+), 72 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1291,79 +1291,10 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + return hvs; + } + +-static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ++static int vc4_hvs_hw_init(struct vc4_hvs *hvs) + { +- struct platform_device *pdev = to_platform_device(dev); +- struct drm_device *drm = dev_get_drvdata(master); +- struct vc4_dev *vc4 = to_vc4_dev(drm); +- struct vc4_hvs *hvs = NULL; +- int ret; +- u32 dispctrl; +- u32 reg, top; +- +- hvs = __vc4_hvs_alloc(vc4, NULL); +- if (IS_ERR(hvs)) +- return PTR_ERR(hvs); +- +- hvs->regs = vc4_ioremap_regs(pdev, 0); +- if (IS_ERR(hvs->regs)) +- return PTR_ERR(hvs->regs); +- +- hvs->regset.base = hvs->regs; +- hvs->regset.regs = hvs_regs; +- hvs->regset.nregs = ARRAY_SIZE(hvs_regs); +- +- if (vc4->gen == VC4_GEN_5) { +- struct rpi_firmware *firmware; +- struct device_node *node; +- unsigned int max_rate; +- +- node = rpi_firmware_find_node(); +- if (!node) +- return -EINVAL; +- +- firmware = rpi_firmware_get(node); +- of_node_put(node); +- if (!firmware) +- return -EPROBE_DEFER; +- +- hvs->core_clk = devm_clk_get(&pdev->dev, NULL); +- if (IS_ERR(hvs->core_clk)) { +- dev_err(&pdev->dev, "Couldn't get core clock\n"); +- return PTR_ERR(hvs->core_clk); +- } +- +- max_rate = rpi_firmware_clk_get_max_rate(firmware, +- RPI_FIRMWARE_CORE_CLK_ID); +- rpi_firmware_put(firmware); +- if (max_rate >= 550000000) +- hvs->vc5_hdmi_enable_hdmi_20 = true; +- +- if (max_rate >= 600000000) +- hvs->vc5_hdmi_enable_4096by2160 = true; +- +- hvs->max_core_rate = max_rate; +- +- ret = clk_prepare_enable(hvs->core_clk); +- if (ret) { +- dev_err(&pdev->dev, "Couldn't enable the core clock\n"); +- return ret; +- } +- } +- +- if (vc4->gen == VC4_GEN_4) +- hvs->dlist = hvs->regs + SCALER_DLIST_START; +- else +- hvs->dlist = hvs->regs + SCALER5_DLIST_START; +- +- /* Upload filter kernels. We only have the one for now, so we +- * keep it around for the lifetime of the driver. +- */ +- ret = vc4_hvs_upload_linear_kernel(hvs, +- &hvs->mitchell_netravali_filter, +- mitchell_netravali_1_3_1_3_kernel); +- if (ret) +- return ret; ++ struct vc4_dev *vc4 = hvs->vc4; ++ u32 dispctrl, reg; + + reg = HVS_READ(SCALER_DISPECTRL); + reg &= ~SCALER_DISPECTRL_DSP2_MUX_MASK; +@@ -1445,6 +1376,86 @@ static int vc4_hvs_bind(struct device *d + + HVS_WRITE(SCALER_DISPCTRL, dispctrl); + ++ return 0; ++} ++ ++static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct drm_device *drm = dev_get_drvdata(master); ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_hvs *hvs = NULL; ++ int ret; ++ u32 reg, top; ++ ++ hvs = __vc4_hvs_alloc(vc4, NULL); ++ if (IS_ERR(hvs)) ++ return PTR_ERR(hvs); ++ ++ hvs->regs = vc4_ioremap_regs(pdev, 0); ++ if (IS_ERR(hvs->regs)) ++ return PTR_ERR(hvs->regs); ++ ++ hvs->regset.base = hvs->regs; ++ hvs->regset.regs = hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(hvs_regs); ++ ++ if (vc4->gen == VC4_GEN_5) { ++ struct rpi_firmware *firmware; ++ struct device_node *node; ++ unsigned int max_rate; ++ ++ node = rpi_firmware_find_node(); ++ if (!node) ++ return -EINVAL; ++ ++ firmware = rpi_firmware_get(node); ++ of_node_put(node); ++ if (!firmware) ++ return -EPROBE_DEFER; ++ ++ hvs->core_clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(hvs->core_clk)) { ++ dev_err(&pdev->dev, "Couldn't get core clock\n"); ++ return PTR_ERR(hvs->core_clk); ++ } ++ ++ max_rate = rpi_firmware_clk_get_max_rate(firmware, ++ RPI_FIRMWARE_CORE_CLK_ID); ++ rpi_firmware_put(firmware); ++ if (max_rate >= 550000000) ++ hvs->vc5_hdmi_enable_hdmi_20 = true; ++ ++ if (max_rate >= 600000000) ++ hvs->vc5_hdmi_enable_4096by2160 = true; ++ ++ hvs->max_core_rate = max_rate; ++ ++ ret = clk_prepare_enable(hvs->core_clk); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't enable the core clock\n"); ++ return ret; ++ } ++ } ++ ++ if (vc4->gen == VC4_GEN_4) ++ hvs->dlist = hvs->regs + SCALER_DLIST_START; ++ else ++ hvs->dlist = hvs->regs + SCALER5_DLIST_START; ++ ++ /* Upload filter kernels. We only have the one for now, so we ++ * keep it around for the lifetime of the driver. ++ */ ++ ret = vc4_hvs_upload_linear_kernel(hvs, ++ &hvs->mitchell_netravali_filter, ++ mitchell_netravali_1_3_1_3_kernel); ++ if (ret) ++ return ret; ++ ++ ret = vc4_hvs_hw_init(hvs); ++ if (ret) ++ return ret; ++ + /* Recompute Composite Output Buffer (COB) allocations for the displays + */ + if (vc4->gen == VC4_GEN_4) { diff --git a/target/linux/bcm27xx/patches-6.1/950-0944-drm-vc4-hvs-Create-cob_init-function.patch b/target/linux/bcm27xx/patches-6.1/950-0944-drm-vc4-hvs-Create-cob_init-function.patch new file mode 100644 index 0000000000..5b2e9745e9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0944-drm-vc4-hvs-Create-cob_init-function.patch @@ -0,0 +1,167 @@ +From 99a13ce3a12303dfb54815637972627a7d207086 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:14:55 +0100 +Subject: [PATCH] drm/vc4: hvs: Create cob_init function + +Just like the HVS itself, the COB parameters will be fairly different in +the BCM2712. + +Let's move the COB parameters computation and its initialisation to a +separate function that will be easier to extend in the future. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 128 ++++++++++++++++++++-------------- + 1 file changed, 74 insertions(+), 54 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1379,6 +1379,77 @@ static int vc4_hvs_hw_init(struct vc4_hv + return 0; + } + ++static int vc4_hvs_cob_init(struct vc4_hvs *hvs) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ u32 reg, top; ++ ++ /* ++ * Recompute Composite Output Buffer (COB) allocations for the ++ * displays ++ */ ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ /* The COB is 20736 pixels, or just over 10 lines at 2048 wide. ++ * The bottom 2048 pixels are full 32bpp RGBA (intended for the ++ * TXP composing RGBA to memory), whilst the remainder are only ++ * 24bpp RGB. ++ * ++ * Assign 3 lines to channels 1 & 2, and just over 4 lines to ++ * channel 0. ++ */ ++ #define VC4_COB_SIZE 20736 ++ #define VC4_COB_LINE_WIDTH 2048 ++ #define VC4_COB_NUM_LINES 3 ++ reg = 0; ++ top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; ++ reg |= (top - 1) << 16; ++ HVS_WRITE(SCALER_DISPBASE2, reg); ++ reg = top; ++ top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; ++ reg |= (top - 1) << 16; ++ HVS_WRITE(SCALER_DISPBASE1, reg); ++ reg = top; ++ top = VC4_COB_SIZE; ++ reg |= (top - 1) << 16; ++ HVS_WRITE(SCALER_DISPBASE0, reg); ++ break; ++ ++ case VC4_GEN_5: ++ /* The COB is 44416 pixels, or 10.8 lines at 4096 wide. ++ * The bottom 4096 pixels are full RGBA (intended for the TXP ++ * composing RGBA to memory), whilst the remainder are only ++ * RGB. Addressing is always pixel wide. ++ * ++ * Assign 3 lines of 4096 to channels 1 & 2, and just over 4 ++ * lines. to channel 0. ++ */ ++ #define VC5_COB_SIZE 44416 ++ #define VC5_COB_LINE_WIDTH 4096 ++ #define VC5_COB_NUM_LINES 3 ++ reg = 0; ++ top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; ++ reg |= top << 16; ++ HVS_WRITE(SCALER_DISPBASE2, reg); ++ top += 16; ++ reg = top; ++ top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; ++ reg |= top << 16; ++ HVS_WRITE(SCALER_DISPBASE1, reg); ++ top += 16; ++ reg = top; ++ top = VC5_COB_SIZE; ++ reg |= top << 16; ++ HVS_WRITE(SCALER_DISPBASE0, reg); ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) + { + struct platform_device *pdev = to_platform_device(dev); +@@ -1386,7 +1457,6 @@ static int vc4_hvs_bind(struct device *d + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_hvs *hvs = NULL; + int ret; +- u32 reg, top; + + hvs = __vc4_hvs_alloc(vc4, NULL); + if (IS_ERR(hvs)) +@@ -1456,59 +1526,9 @@ static int vc4_hvs_bind(struct device *d + if (ret) + return ret; + +- /* Recompute Composite Output Buffer (COB) allocations for the displays +- */ +- if (vc4->gen == VC4_GEN_4) { +- /* The COB is 20736 pixels, or just over 10 lines at 2048 wide. +- * The bottom 2048 pixels are full 32bpp RGBA (intended for the +- * TXP composing RGBA to memory), whilst the remainder are only +- * 24bpp RGB. +- * +- * Assign 3 lines to channels 1 & 2, and just over 4 lines to +- * channel 0. +- */ +- #define VC4_COB_SIZE 20736 +- #define VC4_COB_LINE_WIDTH 2048 +- #define VC4_COB_NUM_LINES 3 +- reg = 0; +- top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; +- reg |= (top - 1) << 16; +- HVS_WRITE(SCALER_DISPBASE2, reg); +- reg = top; +- top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; +- reg |= (top - 1) << 16; +- HVS_WRITE(SCALER_DISPBASE1, reg); +- reg = top; +- top = VC4_COB_SIZE; +- reg |= (top - 1) << 16; +- HVS_WRITE(SCALER_DISPBASE0, reg); +- } else { +- /* The COB is 44416 pixels, or 10.8 lines at 4096 wide. +- * The bottom 4096 pixels are full RGBA (intended for the TXP +- * composing RGBA to memory), whilst the remainder are only +- * RGB. Addressing is always pixel wide. +- * +- * Assign 3 lines of 4096 to channels 1 & 2, and just over 4 +- * lines. to channel 0. +- */ +- #define VC5_COB_SIZE 44416 +- #define VC5_COB_LINE_WIDTH 4096 +- #define VC5_COB_NUM_LINES 3 +- reg = 0; +- top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; +- reg |= top << 16; +- HVS_WRITE(SCALER_DISPBASE2, reg); +- top += 16; +- reg = top; +- top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; +- reg |= top << 16; +- HVS_WRITE(SCALER_DISPBASE1, reg); +- top += 16; +- reg = top; +- top = VC5_COB_SIZE; +- reg |= top << 16; +- HVS_WRITE(SCALER_DISPBASE0, reg); +- } ++ ret = vc4_hvs_cob_init(hvs); ++ if (ret) ++ return ret; + + ret = devm_request_irq(dev, platform_get_irq(pdev, 0), + vc4_hvs_irq_handler, 0, "vc4 hvs", drm); diff --git a/target/linux/bcm27xx/patches-6.1/950-0945-drm-vc4-hvs-Rename-hvs_regs-list.patch b/target/linux/bcm27xx/patches-6.1/950-0945-drm-vc4-hvs-Rename-hvs_regs-list.patch new file mode 100644 index 0000000000..4139d79f02 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0945-drm-vc4-hvs-Rename-hvs_regs-list.patch @@ -0,0 +1,38 @@ +From 7a1c157ac856384c47df38e1de2995f55a111b85 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:41:59 +0100 +Subject: [PATCH] drm/vc4: hvs: Rename hvs_regs list + +The HVS register set has been heavily modified in the BCM2712, and we'll +thus need a separate debugfs_reg32 array for it. + +The name hvs_regs is thus a bit too generic, so let's rename it to +something more specific. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -33,7 +33,7 @@ + #include "vc4_drv.h" + #include "vc4_regs.h" + +-static const struct debugfs_reg32 hvs_regs[] = { ++static const struct debugfs_reg32 vc4_hvs_regs[] = { + VC4_REG32(SCALER_DISPCTRL), + VC4_REG32(SCALER_DISPSTAT), + VC4_REG32(SCALER_DISPID), +@@ -1467,8 +1467,8 @@ static int vc4_hvs_bind(struct device *d + return PTR_ERR(hvs->regs); + + hvs->regset.base = hvs->regs; +- hvs->regset.regs = hvs_regs; +- hvs->regset.nregs = ARRAY_SIZE(hvs_regs); ++ hvs->regset.regs = vc4_hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); + + if (vc4->gen == VC4_GEN_5) { + struct rpi_firmware *firmware; diff --git a/target/linux/bcm27xx/patches-6.1/950-0946-drm-vc4-plane-Change-ptr0_offset-to-an-array.patch b/target/linux/bcm27xx/patches-6.1/950-0946-drm-vc4-plane-Change-ptr0_offset-to-an-array.patch new file mode 100644 index 0000000000..ed55f53fad --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0946-drm-vc4-plane-Change-ptr0_offset-to-an-array.patch @@ -0,0 +1,103 @@ +From 531f66804eb95323f807d240273087fbe162aeee Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 09:56:31 +0100 +Subject: [PATCH] drm/vc4: plane: Change ptr0_offset to an array + +The BCM2712 will have a fairly different dlist, that will feature one +Pointer 0 word for each plane. + +Let's prepare by changing the ptr0_offset variable that holds the offset +in a dlist of the pointer 0 word to an array. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 3 ++- + drivers/gpu/drm/vc4/vc4_plane.c | 18 +++++++++--------- + 2 files changed, 11 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -430,7 +431,7 @@ struct vc4_plane_state { + */ + u32 pos0_offset; + u32 pos2_offset; +- u32 ptr0_offset; ++ u32 ptr0_offset[DRM_FORMAT_MAX_PLANES]; + u32 lbm_offset; + + /* Offset where the plane's dlist was last stored in the +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1242,7 +1242,7 @@ static int vc4_plane_mode_set(struct drm + * + * The pointers may be any byte address. + */ +- vc4_state->ptr0_offset = vc4_state->dlist_count; ++ vc4_state->ptr0_offset[0] = vc4_state->dlist_count; + for (i = 0; i < num_planes; i++) + vc4_dlist_write(vc4_state, vc4_state->offsets[i]); + +@@ -1447,13 +1447,13 @@ void vc4_plane_async_set_fb(struct drm_p + * scanout will start from this address as soon as the FIFO + * needs to refill with pixels. + */ +- writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset]); ++ writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); + + /* Also update the CPU-side dlist copy, so that any later + * atomic updates that don't do a new modeset on our plane + * also use our updated address. + */ +- vc4_state->dlist[vc4_state->ptr0_offset] = addr; ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = addr; + + drm_dev_exit(idx); + } +@@ -1517,8 +1517,8 @@ static void vc4_plane_atomic_async_updat + new_vc4_state->dlist[vc4_state->pos0_offset]; + vc4_state->dlist[vc4_state->pos2_offset] = + new_vc4_state->dlist[vc4_state->pos2_offset]; +- vc4_state->dlist[vc4_state->ptr0_offset] = +- new_vc4_state->dlist[vc4_state->ptr0_offset]; ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = ++ new_vc4_state->dlist[vc4_state->ptr0_offset[0]]; + + /* Note that we can't just call vc4_plane_write_dlist() + * because that would smash the context data that the HVS is +@@ -1528,8 +1528,8 @@ static void vc4_plane_atomic_async_updat + &vc4_state->hw_dlist[vc4_state->pos0_offset]); + writel(vc4_state->dlist[vc4_state->pos2_offset], + &vc4_state->hw_dlist[vc4_state->pos2_offset]); +- writel(vc4_state->dlist[vc4_state->ptr0_offset], +- &vc4_state->hw_dlist[vc4_state->ptr0_offset]); ++ writel(vc4_state->dlist[vc4_state->ptr0_offset[0]], ++ &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); + + drm_dev_exit(idx); + } +@@ -1556,7 +1556,7 @@ static int vc4_plane_atomic_async_check( + if (old_vc4_state->dlist_count != new_vc4_state->dlist_count || + old_vc4_state->pos0_offset != new_vc4_state->pos0_offset || + old_vc4_state->pos2_offset != new_vc4_state->pos2_offset || +- old_vc4_state->ptr0_offset != new_vc4_state->ptr0_offset || ++ old_vc4_state->ptr0_offset[0] != new_vc4_state->ptr0_offset[0] || + vc4_lbm_size(plane->state) != vc4_lbm_size(new_plane_state)) + return -EINVAL; + +@@ -1566,7 +1566,7 @@ static int vc4_plane_atomic_async_check( + for (i = 0; i < new_vc4_state->dlist_count; i++) { + if (i == new_vc4_state->pos0_offset || + i == new_vc4_state->pos2_offset || +- i == new_vc4_state->ptr0_offset || ++ i == new_vc4_state->ptr0_offset[0] || + (new_vc4_state->lbm_offset && + i == new_vc4_state->lbm_offset)) + continue; diff --git a/target/linux/bcm27xx/patches-6.1/950-0947-drm-vc4-hvs-Rework-LBM-alignment.patch b/target/linux/bcm27xx/patches-6.1/950-0947-drm-vc4-hvs-Rework-LBM-alignment.patch new file mode 100644 index 0000000000..3a30b9ca85 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0947-drm-vc4-hvs-Rework-LBM-alignment.patch @@ -0,0 +1,45 @@ +From 2834b58a3b58198e551d8461a0786b75d3d76823 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 13 Apr 2023 10:12:19 +0200 +Subject: [PATCH] drm/vc4: hvs: Rework LBM alignment + +With the introduction of the support for BCM2712, the check of whether +we're running on vc5 or not to compute the LBM alignment requirement +doesn't work anymore. + +Moreover, the LBM size will need to be computed in words for the +BCM2712, while we've had sizes in bytes so far. + +Aligning on either 64 or 32 words is thus fairly harmful on BCM2712, so +let's just explicitly align the size when needed, and then call +drm_mm_insert_node_generic() with an alignment of 1. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_plane.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -744,6 +744,11 @@ static int vc4_plane_allocate_lbm(struct + if (!lbm_size) + return 0; + ++ if (vc4->gen == VC4_GEN_5) ++ lbm_size = ALIGN(lbm_size, 64); ++ else if (vc4->gen == VC4_GEN_4) ++ lbm_size = ALIGN(lbm_size, 32); ++ + drm_dbg_driver(drm, "[PLANE:%d:%s] LBM Allocation Size: %u\n", + plane->base.id, plane->name, lbm_size); + +@@ -759,8 +764,7 @@ static int vc4_plane_allocate_lbm(struct + spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); + ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, + &vc4_state->lbm, +- lbm_size, +- vc4->gen == VC4_GEN_5 ? 64 : 32, ++ lbm_size, 1, + 0, 0); + spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0948-drm-vc4-hvs-Change-prototype-of-__vc4_hvs_alloc-to-p.patch b/target/linux/bcm27xx/patches-6.1/950-0948-drm-vc4-hvs-Change-prototype-of-__vc4_hvs_alloc-to-p.patch new file mode 100644 index 0000000000..2927a3e04e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0948-drm-vc4-hvs-Change-prototype-of-__vc4_hvs_alloc-to-p.patch @@ -0,0 +1,93 @@ +From 23cba2abd5ffbb7337e3f381c4724eaaf01cf5a1 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 15:45:50 +0100 +Subject: [PATCH] drm/vc4: hvs: Change prototype of __vc4_hvs_alloc to pass + registers + +The BCM2712 HVS has registers to report the size of the various SRAM the +driver uses, and their size actually differ depending on the stepping. + +The initialisation of the memory pools happen in the __vc4_hvs_alloc() +function that also allocates the main HVS structure, that will then hold +the pointer to the memory mapping of the registers. + +This creates some kind of circular dependency that we can break by +passing the mapping pointer as an argument for __vc4_hvs_alloc() to use +to query to get the SRAM sizes and initialise the memory pools +accordingly. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 2 +- + drivers/gpu/drm/vc4/vc4_drv.h | 4 +++- + drivers/gpu/drm/vc4/vc4_hvs.c | 16 ++++++++++------ + 3 files changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -173,7 +173,7 @@ static struct vc4_dev *__mock_device(str + vc4->dev = dev; + vc4->gen = gen; + +- vc4->hvs = __vc4_hvs_alloc(vc4, NULL); ++ vc4->hvs = __vc4_hvs_alloc(vc4, NULL, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs); + + drm = &vc4->base; +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -1092,7 +1092,9 @@ void vc4_irq_reset(struct drm_device *de + + /* vc4_hvs.c */ + extern struct platform_driver vc4_hvs_driver; +-struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pdev); ++struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, ++ void __iomem *regs, ++ struct platform_device *pdev); + void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int output); + int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output); + u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo); +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1248,7 +1248,9 @@ int vc4_hvs_debugfs_init(struct drm_mino + return 0; + } + +-struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pdev) ++struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, ++ void __iomem *regs, ++ struct platform_device *pdev) + { + struct drm_device *drm = &vc4->base; + struct vc4_hvs *hvs; +@@ -1258,6 +1260,7 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + return ERR_PTR(-ENOMEM); + + hvs->vc4 = vc4; ++ hvs->regs = regs; + hvs->pdev = pdev; + + spin_lock_init(&hvs->mm_lock); +@@ -1456,16 +1459,17 @@ static int vc4_hvs_bind(struct device *d + struct drm_device *drm = dev_get_drvdata(master); + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_hvs *hvs = NULL; ++ void __iomem *regs; + int ret; + +- hvs = __vc4_hvs_alloc(vc4, NULL); ++ regs = vc4_ioremap_regs(pdev, 0); ++ if (IS_ERR(regs)) ++ return PTR_ERR(regs); ++ ++ hvs = __vc4_hvs_alloc(vc4, regs, pdev); + if (IS_ERR(hvs)) + return PTR_ERR(hvs); + +- hvs->regs = vc4_ioremap_regs(pdev, 0); +- if (IS_ERR(hvs->regs)) +- return PTR_ERR(hvs->regs); +- + hvs->regset.base = hvs->regs; + hvs->regset.regs = vc4_hvs_regs; + hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); diff --git a/target/linux/bcm27xx/patches-6.1/950-0949-drm-vc4-UV-planes-vertical-scaling-must-always-be-en.patch b/target/linux/bcm27xx/patches-6.1/950-0949-drm-vc4-UV-planes-vertical-scaling-must-always-be-en.patch new file mode 100644 index 0000000000..4a51862487 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0949-drm-vc4-UV-planes-vertical-scaling-must-always-be-en.patch @@ -0,0 +1,30 @@ +From 03e0e348df7b685439f2db61ec2d8c8da25d1217 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 23 Aug 2023 17:48:23 +0100 +Subject: [PATCH] drm/vc4: UV planes vertical scaling must always be enabled + +It has been observed that a YUV422 unity scaled plane isn't displayed. +Enabling vertical scaling on the UV planes solves this. There is +already a similar clause to always enable horizontal scaling on the +UV planes. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -522,6 +522,12 @@ static int vc4_plane_setup_clipping_and_ + */ + if (vc4_state->x_scaling[1] == VC4_SCALING_NONE) + vc4_state->x_scaling[1] = VC4_SCALING_PPF; ++ ++ /* Similarly UV needs vertical scaling to be enabled. ++ * Without this a 1:1 scaled YUV422 plane isn't rendered. ++ */ ++ if (vc4_state->y_scaling[1] == VC4_SCALING_NONE) ++ vc4_state->y_scaling[1] = VC4_SCALING_PPF; + } else { + vc4_state->is_yuv = false; + vc4_state->x_scaling[1] = VC4_SCALING_NONE; diff --git a/target/linux/bcm27xx/patches-6.1/950-0950-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch b/target/linux/bcm27xx/patches-6.1/950-0950-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch new file mode 100644 index 0000000000..8e36b79794 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0950-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch @@ -0,0 +1,39 @@ +From e5e7679d634b10e88df340c85cd8368c9f9989eb Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 5 Sep 2023 19:38:24 +0100 +Subject: [PATCH] drm/vc4: hdmi: Avoid hang with debug registers when suspended + +Trying to read /sys/kernel/debug/dri/1/hdmi1_regs +when the hdmi is disconnected results in a fatal system hang. + +This is due to the pm suspend code disabling the dvp clock. +That is just a gate of the 108MHz clock in DVP_HT_RPI_MISC_CONFIG, +which results in accesses hanging AXI bus. + +Protect against this. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -193,6 +193,8 @@ static int vc4_hdmi_debugfs_regs(struct + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; + ++ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); ++ + drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); + drm_print_regset32(&p, &vc4_hdmi->hd_regset); + drm_print_regset32(&p, &vc4_hdmi->cec_regset); +@@ -202,6 +204,8 @@ static int vc4_hdmi_debugfs_regs(struct + drm_print_regset32(&p, &vc4_hdmi->ram_regset); + drm_print_regset32(&p, &vc4_hdmi->rm_regset); + ++ pm_runtime_put(&vc4_hdmi->pdev->dev); ++ + drm_dev_exit(idx); + + return 0; diff --git a/target/linux/bcm27xx/patches-6.1/950-0951-drm-vc4-Move-the-buffer-offset-out-of-the-vc4_plane_.patch b/target/linux/bcm27xx/patches-6.1/950-0951-drm-vc4-Move-the-buffer-offset-out-of-the-vc4_plane_.patch new file mode 100644 index 0000000000..eeb2a93b5c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0951-drm-vc4-Move-the-buffer-offset-out-of-the-vc4_plane_.patch @@ -0,0 +1,154 @@ +From 11cf37e741b439b26fe932750bde841a16a96828 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 25 Sep 2023 16:57:07 +0100 +Subject: [PATCH] drm/vc4: Move the buffer offset out of the vc4_plane_state + +The offset fields in vc4_plane_state are described as being +the offset for each buffer in the bo, however it is used to +store the complete DMA address that is then written into the +register. + +The DMA address including the fb ofset can be retrieved +using drm_fb_dma_get_gem_addr, and the offset adjustment due to +clipping is local to vc4_plane_mode_set. +Drop the offset field from the state, and compute the complete +DMA address in vc4_plane_mode_set. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 5 ---- + drivers/gpu/drm/vc4/vc4_plane.c | 51 +++++++++++++-------------------- + 2 files changed, 20 insertions(+), 36 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -451,11 +451,6 @@ struct vc4_plane_state { + bool is_unity; + bool is_yuv; + +- /* Offset to start scanning out from the start of the plane's +- * BO. +- */ +- u32 offsets[3]; +- + /* Our allocation in LBM for temporary storage during scaling. */ + struct drm_mm_node lbm; + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -450,12 +450,11 @@ static int vc4_plane_setup_clipping_and_ + { + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + struct drm_framebuffer *fb = state->fb; +- struct drm_gem_dma_object *bo; + int num_planes = fb->format->num_planes; + struct drm_crtc_state *crtc_state; + u32 h_subsample = fb->format->hsub; + u32 v_subsample = fb->format->vsub; +- int i, ret; ++ int ret; + + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); +@@ -469,11 +468,6 @@ static int vc4_plane_setup_clipping_and_ + if (ret) + return ret; + +- for (i = 0; i < num_planes; i++) { +- bo = drm_fb_dma_get_gem_obj(fb, i); +- vc4_state->offsets[i] = bo->dma_addr + fb->offsets[i]; +- } +- + vc4_state->src_x = state->src.x1; + vc4_state->src_y = state->src.y1; + vc4_state->src_w[0] = state->src.x2 - vc4_state->src_x; +@@ -896,6 +890,7 @@ static int vc4_plane_mode_set(struct drm + u32 width, height; + u32 hvs_format = format->hvs; + unsigned int rotation; ++ u32 offsets[3] = { 0 }; + int ret, i; + + if (vc4_state->dlist_initialized) +@@ -943,13 +938,8 @@ static int vc4_plane_mode_set(struct drm + * out. + */ + for (i = 0; i < num_planes; i++) { +- vc4_state->offsets[i] += src_y / +- (i ? v_subsample : 1) * +- fb->pitches[i]; +- +- vc4_state->offsets[i] += src_x / +- (i ? h_subsample : 1) * +- fb->format->cpp[i]; ++ offsets[i] += src_y / (i ? v_subsample : 1) * fb->pitches[i]; ++ offsets[i] += src_x / (i ? h_subsample : 1) * fb->format->cpp[i]; + } + + break; +@@ -1004,19 +994,18 @@ static int vc4_plane_mode_set(struct drm + VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | + VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | + VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); +- vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); +- vc4_state->offsets[0] += subtile_y << 8; +- vc4_state->offsets[0] += utile_y << 4; ++ offsets[0] += tiles_t * (tiles_w << tile_size_shift); ++ offsets[0] += subtile_y << 8; ++ offsets[0] += utile_y << 4; + + /* Rows of tiles alternate left-to-right and right-to-left. */ + if (tiles_t & 1) { + pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR; +- vc4_state->offsets[0] += (tiles_w - tiles_l) << +- tile_size_shift; +- vc4_state->offsets[0] -= (1 + !tile_y) << 10; ++ offsets[0] += (tiles_w - tiles_l) << tile_size_shift; ++ offsets[0] -= (1 + !tile_y) << 10; + } else { +- vc4_state->offsets[0] += tiles_l << tile_size_shift; +- vc4_state->offsets[0] += tile_y << 10; ++ offsets[0] += tiles_l << tile_size_shift; ++ offsets[0] += tile_y << 10; + } + + break; +@@ -1105,11 +1094,9 @@ static int vc4_plane_mode_set(struct drm + + tile = src_x / pix_per_tile; + +- vc4_state->offsets[i] += param * tile_w * tile; +- vc4_state->offsets[i] += src_y / +- (i ? v_subsample : 1) * +- tile_w; +- vc4_state->offsets[i] += x_off & ~(i ? 1 : 0); ++ offsets[i] += param * tile_w * tile; ++ offsets[i] += src_y / (i ? v_subsample : 1) * tile_w; ++ offsets[i] += x_off & ~(i ? 1 : 0); + } + + pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); +@@ -1253,8 +1240,12 @@ static int vc4_plane_mode_set(struct drm + * The pointers may be any byte address. + */ + vc4_state->ptr0_offset[0] = vc4_state->dlist_count; +- for (i = 0; i < num_planes; i++) +- vc4_dlist_write(vc4_state, vc4_state->offsets[i]); ++ ++ for (i = 0; i < num_planes; i++) { ++ dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); ++ ++ vc4_dlist_write(vc4_state, paddr + offsets[i]); ++ } + + /* Pointer Context Word 0/1/2: Written by the HVS */ + for (i = 0; i < num_planes; i++) +@@ -1518,8 +1509,6 @@ static void vc4_plane_atomic_async_updat + sizeof(vc4_state->y_scaling)); + vc4_state->is_unity = new_vc4_state->is_unity; + vc4_state->is_yuv = new_vc4_state->is_yuv; +- memcpy(vc4_state->offsets, new_vc4_state->offsets, +- sizeof(vc4_state->offsets)); + vc4_state->needs_bg_fill = new_vc4_state->needs_bg_fill; + + /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0952-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch b/target/linux/bcm27xx/patches-6.1/950-0952-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch new file mode 100644 index 0000000000..01ad932415 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0952-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch @@ -0,0 +1,33 @@ +From 3660abb4a8523e988f1345985e89149804e50ebe Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 24 Aug 2023 15:36:21 +0100 +Subject: [PATCH] drm/vc4: Fix dlist debug not resetting the next entry pointer + +The debug function to display the dlists didn't reset next_entry_start +when starting each display, so resulting in not stopping the +list at the correct place. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -110,7 +110,7 @@ static int vc4_hvs_debugfs_dlist(struct + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + struct drm_printer p = drm_seq_file_printer(m); +- unsigned int next_entry_start = 0; ++ unsigned int next_entry_start; + unsigned int i, j; + u32 dlist_word, dispstat; + +@@ -124,6 +124,7 @@ static int vc4_hvs_debugfs_dlist(struct + } + + drm_printf(&p, "HVS chan %u:\n", i); ++ next_entry_start = 0; + + for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) { + dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); diff --git a/target/linux/bcm27xx/patches-6.1/950-0953-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch b/target/linux/bcm27xx/patches-6.1/950-0953-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch new file mode 100644 index 0000000000..d41d53ecbe --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0953-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch @@ -0,0 +1,57 @@ +From ebf11a4cfd9f1236fb9eeb7e32e87b18f5f56f16 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 1 Sep 2023 13:45:08 +0100 +Subject: [PATCH] drm: vc4: Remove incorrect limit from hvs_dlist debugfs + function + +The debugfs function to dump dlists aborted at 256 bytes, +when actually the dlist memory is generally significantly +larger but varies based on SoC. + +We already have the correct limit in __vc4_hvs_alloc, so +store it for use in the debugfs dlist function. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_hvs.c | 5 ++++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -341,6 +341,7 @@ struct vc4_hvs { + struct platform_device *pdev; + void __iomem *regs; + u32 __iomem *dlist; ++ unsigned int dlist_mem_size; + + struct clk *core_clk; + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -110,6 +110,7 @@ static int vc4_hvs_debugfs_dlist(struct + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + struct drm_printer p = drm_seq_file_printer(m); ++ unsigned int dlist_mem_size = hvs->dlist_mem_size; + unsigned int next_entry_start; + unsigned int i, j; + u32 dlist_word, dispstat; +@@ -126,7 +127,7 @@ static int vc4_hvs_debugfs_dlist(struct + drm_printf(&p, "HVS chan %u:\n", i); + next_entry_start = 0; + +- for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) { ++ for (j = HVS_READ(SCALER_DISPLISTX(i)); j < dlist_mem_size; j++) { + dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); + drm_printf(&p, "dlist: %02d: 0x%08x\n", j, + dlist_word); +@@ -1278,6 +1279,8 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + HVS_BOOTLOADER_DLIST_END, + (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END); + ++ hvs->dlist_mem_size = dlist_size; ++ + /* Set up the HVS LBM memory manager. We could have some more + * complicated data structure that allowed reuse of LBM areas + * between planes when they don't overlap on the screen, but diff --git a/target/linux/bcm27xx/patches-6.1/950-0954-drm-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch b/target/linux/bcm27xx/patches-6.1/950-0954-drm-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch new file mode 100644 index 0000000000..640b0ea757 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0954-drm-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch @@ -0,0 +1,50 @@ +From 712bccec241e84e28ccb725fae87d3255d039f42 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Thu, 22 Jun 2023 14:06:40 +0100 +Subject: [PATCH] drm/vc4: hvs: Remove ABORT_ON_EMPTY flag + +ABORT_ON_EMPTY chooses whether the HVS abandons the current frame +when it experiences an underflow, or attempts to continue. + +In theory the frame should be black from the point of underflow, +compared to a shift of sebsequent pixels to the left. + +Unfortunately it seems to put the HVS is a bad state where it is not +possible to recover simply. This typically requires a reboot +following the 'flip done timed out message'. + +Discussion with Broadcom has suggested we don't use this flag. +All their testing is done with it disabled. + +Additionally setting BLANK_INSERT_EN causes the HDMI to output +blank pixels on an underflow which avoids it losing sync. + +After this change a 'flip done timed out' due to sdram bandwidth +starvation or too low a clock is recoverable once the situation improves. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 1 + + drivers/gpu/drm/vc4/vc4_regs.h | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -1866,6 +1866,7 @@ static void vc4_hdmi_encoder_post_crtc_e + VC4_HD_VID_CTL_CLRRGB | + VC4_HD_VID_CTL_UNDERFLOW_ENABLE | + VC4_HD_VID_CTL_FRAME_COUNTER_RESET | ++ VC4_HD_VID_CTL_BLANK_INSERT_EN | + (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | + (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); + +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -799,6 +799,7 @@ enum { + # define VC4_HD_VID_CTL_CLRSYNC BIT(24) + # define VC4_HD_VID_CTL_CLRRGB BIT(23) + # define VC4_HD_VID_CTL_BLANKPIX BIT(18) ++# define VC4_HD_VID_CTL_BLANK_INSERT_EN BIT(16) + + # define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5) + # define VC4_HD_CSC_CTL_ORDER_SHIFT 5 diff --git a/target/linux/bcm27xx/patches-6.1/950-0955-drm-vc4-Enable-SCALER_CONTROL-early-in-HVS-init.patch b/target/linux/bcm27xx/patches-6.1/950-0955-drm-vc4-Enable-SCALER_CONTROL-early-in-HVS-init.patch new file mode 100644 index 0000000000..3060c0201f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0955-drm-vc4-Enable-SCALER_CONTROL-early-in-HVS-init.patch @@ -0,0 +1,59 @@ +From 542ba979b4fa1e07ff2ad2dabbdc12e92b80ed46 Mon Sep 17 00:00:00 2001 +From: Tim Gover +Date: Thu, 13 Jul 2023 17:47:22 +0100 +Subject: [PATCH] drm/vc4: Enable SCALER_CONTROL early in HVS init + +Always enable SCALER_CONTROL before attempting other HVS +operations. It's safe to write to some parts of the HVS but +in general it's dangerous to do this because it can cause bus +lockups. + +Signed-off-by: Tim Gover +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1303,6 +1303,10 @@ static int vc4_hvs_hw_init(struct vc4_hv + struct vc4_dev *vc4 = hvs->vc4; + u32 dispctrl, reg; + ++ dispctrl = HVS_READ(SCALER_DISPCTRL); ++ dispctrl |= SCALER_DISPCTRL_ENABLE; ++ HVS_WRITE(SCALER_DISPCTRL, dispctrl); ++ + reg = HVS_READ(SCALER_DISPECTRL); + reg &= ~SCALER_DISPECTRL_DSP2_MUX_MASK; + HVS_WRITE(SCALER_DISPECTRL, +@@ -1324,8 +1328,6 @@ static int vc4_hvs_hw_init(struct vc4_hv + reg | VC4_SET_FIELD(3, SCALER_DISPDITHER_DSP5_MUX)); + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- +- dispctrl |= SCALER_DISPCTRL_ENABLE; + dispctrl |= SCALER_DISPCTRL_DISPEIRQ(0) | + SCALER_DISPCTRL_DISPEIRQ(1) | + SCALER_DISPCTRL_DISPEIRQ(2); +@@ -1521,6 +1523,10 @@ static int vc4_hvs_bind(struct device *d + else + hvs->dlist = hvs->regs + SCALER5_DLIST_START; + ++ ret = vc4_hvs_hw_init(hvs); ++ if (ret) ++ return ret; ++ + /* Upload filter kernels. We only have the one for now, so we + * keep it around for the lifetime of the driver. + */ +@@ -1530,10 +1536,6 @@ static int vc4_hvs_bind(struct device *d + if (ret) + return ret; + +- ret = vc4_hvs_hw_init(hvs); +- if (ret) +- return ret; +- + ret = vc4_hvs_cob_init(hvs); + if (ret) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-0956-dt-bindings-display-Add-BCM2712-HDMI-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0956-dt-bindings-display-Add-BCM2712-HDMI-bindings.patch new file mode 100644 index 0000000000..dab1fff2e3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0956-dt-bindings-display-Add-BCM2712-HDMI-bindings.patch @@ -0,0 +1,26 @@ +From aed3dadaa6fb4c38275b264ecc0ff5ebe0408b82 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:02 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 HDMI bindings + +The BCM2712 HDMI controller uses a slightly different HDMI controller +than the BCM2711, and a completely different PHY. + +Let's introduce a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml +@@ -14,6 +14,8 @@ properties: + enum: + - brcm,bcm2711-hdmi0 + - brcm,bcm2711-hdmi1 ++ - brcm,bcm2712-hdmi0 ++ - brcm,bcm2712-hdmi1 + + reg: + items: diff --git a/target/linux/bcm27xx/patches-6.1/950-0957-dt-bindings-display-Add-BCM2712-HVS-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0957-dt-bindings-display-Add-BCM2712-HVS-bindings.patch new file mode 100644 index 0000000000..e28100734f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0957-dt-bindings-display-Add-BCM2712-HVS-bindings.patch @@ -0,0 +1,34 @@ +From 2f5a75f9687553d6e91fcc09b233f5f6176b3681 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:14 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 HVS bindings + +The BCM2712 has a completely different HVS than the previous +generations, so let's add a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2835-hvs.yaml | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml +@@ -13,6 +13,7 @@ properties: + compatible: + enum: + - brcm,bcm2711-hvs ++ - brcm,bcm2712-hvs + - brcm,bcm2835-hvs + + reg: +@@ -36,7 +37,9 @@ if: + properties: + compatible: + contains: +- const: brcm,bcm2711-hvs ++ enum: ++ - brcm,bcm2711-hvs ++ - brcm,bcm2712-hvs + + then: + required: diff --git a/target/linux/bcm27xx/patches-6.1/950-0958-dt-bindings-display-Add-BCM2712-PixelValve-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0958-dt-bindings-display-Add-BCM2712-PixelValve-bindings.patch new file mode 100644 index 0000000000..b37c1274ae --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0958-dt-bindings-display-Add-BCM2712-PixelValve-bindings.patch @@ -0,0 +1,28 @@ +From 9f26d5827745df2c59e5559fd59a5045a4ad7ce0 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:27 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 PixelValve bindings + +The BCM2712 has 3 different pixelvalves that are similar to the ones +found in the previous generations but with slightly different +capabilities. + +Express that using a new set of compatibles. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml +@@ -20,6 +20,9 @@ properties: + - brcm,bcm2711-pixelvalve2 + - brcm,bcm2711-pixelvalve3 + - brcm,bcm2711-pixelvalve4 ++ - brcm,bcm2712-pixelvalve0 ++ - brcm,bcm2712-pixelvalve1 ++ - brcm,bcm2712-pixelvalve2 + + reg: + maxItems: 1 diff --git a/target/linux/bcm27xx/patches-6.1/950-0959-dt-bindings-display-Add-BCM2712-MOP-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0959-dt-bindings-display-Add-BCM2712-MOP-bindings.patch new file mode 100644 index 0000000000..ea537522cc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0959-dt-bindings-display-Add-BCM2712-MOP-bindings.patch @@ -0,0 +1,28 @@ +From 07f90ad6a81d9ed923ee0da05541718baf49fb3c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:36 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 MOP bindings + +The BCM2712 has a MOP controller which is basically a new revision of +the TXP. + +Express that by adding a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2835-txp.yaml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml +@@ -11,7 +11,9 @@ maintainers: + + properties: + compatible: +- const: brcm,bcm2835-txp ++ enum: ++ - brcm,bcm2712-mop ++ - brcm,bcm2835-txp + + reg: + maxItems: 1 diff --git a/target/linux/bcm27xx/patches-6.1/950-0960-dt-bindings-display-Add-BCM2712-MOPLET-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0960-dt-bindings-display-Add-BCM2712-MOPLET-bindings.patch new file mode 100644 index 0000000000..97aaf5bb7a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0960-dt-bindings-display-Add-BCM2712-MOPLET-bindings.patch @@ -0,0 +1,25 @@ +From e4a3722d08c723f1212bfbdcb52710de8340720a Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:36 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 MOPLET bindings + +The BCM2712 has a MOPLET controller which is basically a TXP without the +transpose feature. + +Express that by adding a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml +@@ -13,6 +13,7 @@ properties: + compatible: + enum: + - brcm,bcm2712-mop ++ - brcm,bcm2712-moplet + - brcm,bcm2835-txp + + reg: diff --git a/target/linux/bcm27xx/patches-6.1/950-0961-dt-bindings-display-Add-BCM2712-KMS-driver-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0961-dt-bindings-display-Add-BCM2712-KMS-driver-bindings.patch new file mode 100644 index 0000000000..420c66ce66 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0961-dt-bindings-display-Add-BCM2712-KMS-driver-bindings.patch @@ -0,0 +1,23 @@ +From e66d4b49a027257c347fa57ce6972f08747c0917 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:51 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 KMS driver bindings + +The BCM2712 SoC comes with a new variation of the videocore display +pipeline. Let's create a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml +@@ -18,6 +18,7 @@ properties: + compatible: + enum: + - brcm,bcm2711-vc5 ++ - brcm,bcm2712-vc6 + - brcm,bcm2835-vc4 + - brcm,cygnus-vc4 + diff --git a/target/linux/bcm27xx/patches-6.1/950-0962-drm-vc4-drv-Support-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0962-drm-vc4-drv-Support-BCM2712.patch new file mode 100644 index 0000000000..57a797ce18 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0962-drm-vc4-drv-Support-BCM2712.patch @@ -0,0 +1,47 @@ +From 847ec495822ad512dd9f1a58a85dabea01534855 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:29:52 +0100 +Subject: [PATCH] drm/vc4: drv: Support BCM2712 + +The BCM2712 has an improved display pipeline, most notably with a +different HVS and only HDMI and writeback outputs. + +Let's introduce it as a new VideoCore generation and compatible. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.c | 5 ++++- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -310,7 +310,9 @@ static int vc4_drm_bind(struct device *d + + dev->coherent_dma_mask = DMA_BIT_MASK(32); + +- if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) ++ if (of_device_is_compatible(dev->of_node, "brcm,bcm2712-vc6")) ++ gen = VC4_GEN_6; ++ else if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) + gen = VC4_GEN_5; + else + gen = VC4_GEN_4; +@@ -475,6 +477,7 @@ static int vc4_platform_drm_remove(struc + + static const struct of_device_id vc4_of_match[] = { + { .compatible = "brcm,bcm2711-vc5", }, ++ { .compatible = "brcm,bcm2712-vc6", }, + { .compatible = "brcm,bcm2835-vc4", }, + { .compatible = "brcm,cygnus-vc4", }, + {}, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -84,6 +84,7 @@ struct vc4_perfmon { + enum vc4_gen { + VC4_GEN_4, + VC4_GEN_5, ++ VC4_GEN_6, + }; + + struct vc4_dev { diff --git a/target/linux/bcm27xx/patches-6.1/950-0963-drm-vc4-hvs-Support-BCM2712-HVS.patch b/target/linux/bcm27xx/patches-6.1/950-0963-drm-vc4-hvs-Support-BCM2712-HVS.patch new file mode 100644 index 0000000000..9659432294 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0963-drm-vc4-hvs-Support-BCM2712-HVS.patch @@ -0,0 +1,2139 @@ +From e84da235223d0209165183c430692dde5c69854c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:25:16 +0100 +Subject: [PATCH] drm/vc4: hvs: Support BCM2712 HVS + +The HVS found in the BCM2712, while having a similar role, is very +different from the one found in the previous SoCs. Indeed, the register +layout is fairly different, and the DLIST format is new as well. + +Let's introduce the needed functions to support the new HVS. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 47 ++- + drivers/gpu/drm/vc4/vc4_drv.c | 8 +- + drivers/gpu/drm/vc4/vc4_drv.h | 18 + + drivers/gpu/drm/vc4/vc4_hvs.c | 626 ++++++++++++++++++++++++++++--- + drivers/gpu/drm/vc4/vc4_kms.c | 102 ++++- + drivers/gpu/drm/vc4/vc4_plane.c | 641 +++++++++++++++++++++++++++++++- + drivers/gpu/drm/vc4/vc4_regs.h | 181 +++++++++ + 7 files changed, 1540 insertions(+), 83 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -82,13 +82,22 @@ static unsigned int + vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel) + { + struct vc4_hvs *hvs = vc4->hvs; +- u32 dispbase = HVS_READ(SCALER_DISPBASEX(channel)); ++ u32 dispbase, top, base; ++ + /* Top/base are supposed to be 4-pixel aligned, but the + * Raspberry Pi firmware fills the low bits (which are + * presumably ignored). + */ +- u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3; +- u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3; ++ ++ if (vc4->gen >= VC4_GEN_6) { ++ dispbase = HVS_READ(SCALER6_DISPX_COB(channel)); ++ top = VC4_GET_FIELD(dispbase, SCALER6_DISPX_COB_TOP) & ~3; ++ base = VC4_GET_FIELD(dispbase, SCALER6_DISPX_COB_BASE) & ~3; ++ } else { ++ dispbase = HVS_READ(SCALER_DISPBASEX(channel)); ++ top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3; ++ base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3; ++ } + + return top - base + 4; + } +@@ -121,7 +130,10 @@ static bool vc4_crtc_get_scanout_positio + * Read vertical scanline which is currently composed for our + * pixelvalve by the HVS, and also the scaler status. + */ +- val = HVS_READ(SCALER_DISPSTATX(channel)); ++ if (vc4->gen >= VC4_GEN_6) ++ val = HVS_READ(SCALER6_DISPX_STATUS(channel)); ++ else ++ val = HVS_READ(SCALER_DISPSTATX(channel)); + + /* Get optional system timestamp after query. */ + if (etime) +@@ -130,7 +142,12 @@ static bool vc4_crtc_get_scanout_positio + /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ + + /* Vertical position of hvs composed scanline. */ +- *vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ *vpos = VC4_GET_FIELD(val, SCALER6_DISPX_STATUS_YLINE); ++ else ++ *vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE); ++ + *hpos = 0; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { +@@ -475,8 +492,10 @@ static void require_hvs_enabled(struct d + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + +- WARN_ON_ONCE((HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE) != +- SCALER_DISPCTRL_ENABLE); ++ if (vc4->gen >= VC4_GEN_6) ++ WARN_ON_ONCE(!(HVS_READ(SCALER6_CONTROL) & SCALER6_CONTROL_HVS_EN)); ++ else ++ WARN_ON_ONCE(!(HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE)); + } + + static int vc4_crtc_disable(struct drm_crtc *crtc, +@@ -804,14 +823,21 @@ static void vc4_crtc_handle_page_flip(st + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; ++ unsigned int current_dlist; + u32 chan = vc4_crtc->current_hvs_channel; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + spin_lock(&vc4_crtc->irq_lock); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ current_dlist = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_DL(chan)), ++ SCALER6_DISPX_DL_LACT); ++ else ++ current_dlist = HVS_READ(SCALER_DISPLACTX(chan)); ++ + if (vc4_crtc->event && +- (vc4_crtc->current_dlist == HVS_READ(SCALER_DISPLACTX(chan)) || +- vc4_crtc->feeds_txp)) { ++ (vc4_crtc->current_dlist == current_dlist || vc4_crtc->feeds_txp)) { + drm_crtc_send_vblank_event(crtc, vc4_crtc->event); + vc4_crtc->event = NULL; + drm_crtc_vblank_put(crtc); +@@ -822,7 +848,8 @@ static void vc4_crtc_handle_page_flip(st + * the CRTC and encoder already reconfigured, leading to + * underruns. This can be seen when reconfiguring the CRTC. + */ +- vc4_hvs_unmask_underrun(hvs, chan); ++ if (vc4->gen < VC4_GEN_6) ++ vc4_hvs_unmask_underrun(hvs, chan); + } + spin_unlock(&vc4_crtc->irq_lock); + spin_unlock_irqrestore(&dev->event_lock, flags); +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -277,6 +277,7 @@ static const struct of_device_id vc4_dma + { .compatible = "brcm,bcm2711-hvs" }, + { .compatible = "brcm,bcm2835-hvs" }, + { .compatible = "brcm,bcm2711-hvs" }, ++ { .compatible = "brcm,bcm2712-hvs" }, + { .compatible = "raspberrypi,rpi-firmware-kms" }, + { .compatible = "brcm,bcm2835-v3d" }, + { .compatible = "brcm,cygnus-v3d" }, +@@ -308,8 +309,6 @@ static int vc4_drm_bind(struct device *d + enum vc4_gen gen; + int ret = 0; + +- dev->coherent_dma_mask = DMA_BIT_MASK(32); +- + if (of_device_is_compatible(dev->of_node, "brcm,bcm2712-vc6")) + gen = VC4_GEN_6; + else if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) +@@ -322,6 +321,11 @@ static int vc4_drm_bind(struct device *d + else + driver = &vc4_drm_driver; + ++ if (gen >= VC4_GEN_6) ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36)); ++ else ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); ++ + node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches, + NULL); + if (node) { +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -345,8 +345,10 @@ struct vc4_hvs { + unsigned int dlist_mem_size; + + struct clk *core_clk; ++ struct clk *disp_clk; + + struct { ++ unsigned int desc; + unsigned int enabled: 1; + } eof_irq[HVS_NUM_CHANNELS]; + +@@ -358,6 +360,11 @@ struct vc4_hvs { + struct drm_mm dlist_mm; + /* Memory manager for the LBM memory used by HVS scaling. */ + struct drm_mm lbm_mm; ++ ++ /* Memory manager for the UPM memory used for prefetching. */ ++ struct drm_mm upm_mm; ++ struct ida upm_handles; ++ + spinlock_t mm_lock; + + struct list_head stale_dlist_entries; +@@ -382,6 +389,8 @@ struct vc4_hvs { + bool vc5_hdmi_enable_4096by2160; + }; + ++#define HVS_UBM_WORD_SIZE 256 ++ + struct vc4_hvs_state { + struct drm_private_state base; + unsigned long core_clock_rate; +@@ -456,6 +465,15 @@ struct vc4_plane_state { + /* Our allocation in LBM for temporary storage during scaling. */ + struct drm_mm_node lbm; + ++ /* Our allocation in UPM for prefetching. */ ++ struct drm_mm_node upm[DRM_FORMAT_MAX_PLANES]; ++ ++ /* The Unified Pre-Fetcher Handle */ ++ unsigned int upm_handle[DRM_FORMAT_MAX_PLANES]; ++ ++ /* Number of lines to pre-fetch */ ++ unsigned int upm_buffer_lines; ++ + /* Set when the plane has per-pixel alpha content or does not cover + * the entire screen. This is a hint to the CRTC that it might need + * to enable background color fill. +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -67,6 +67,80 @@ static const struct debugfs_reg32 vc4_hv + VC4_REG32(SCALER_OLEDCOEF2), + }; + ++static const struct debugfs_reg32 vc6_hvs_regs[] = { ++ VC4_REG32(SCALER6_VERSION), ++ VC4_REG32(SCALER6_CXM_SIZE), ++ VC4_REG32(SCALER6_LBM_SIZE), ++ VC4_REG32(SCALER6_UBM_SIZE), ++ VC4_REG32(SCALER6_COBA_SIZE), ++ VC4_REG32(SCALER6_COB_SIZE), ++ VC4_REG32(SCALER6_CONTROL), ++ VC4_REG32(SCALER6_FETCHER_STATUS), ++ VC4_REG32(SCALER6_FETCH_STATUS), ++ VC4_REG32(SCALER6_HANDLE_ERROR), ++ VC4_REG32(SCALER6_DISP0_CTRL0), ++ VC4_REG32(SCALER6_DISP0_CTRL1), ++ VC4_REG32(SCALER6_DISP0_BGND), ++ VC4_REG32(SCALER6_DISP0_LPTRS), ++ VC4_REG32(SCALER6_DISP0_COB), ++ VC4_REG32(SCALER6_DISP0_STATUS), ++ VC4_REG32(SCALER6_DISP0_DL), ++ VC4_REG32(SCALER6_DISP0_RUN), ++ VC4_REG32(SCALER6_DISP1_CTRL0), ++ VC4_REG32(SCALER6_DISP1_CTRL1), ++ VC4_REG32(SCALER6_DISP1_BGND), ++ VC4_REG32(SCALER6_DISP1_LPTRS), ++ VC4_REG32(SCALER6_DISP1_COB), ++ VC4_REG32(SCALER6_DISP1_STATUS), ++ VC4_REG32(SCALER6_DISP1_DL), ++ VC4_REG32(SCALER6_DISP1_RUN), ++ VC4_REG32(SCALER6_DISP2_CTRL0), ++ VC4_REG32(SCALER6_DISP2_CTRL1), ++ VC4_REG32(SCALER6_DISP2_BGND), ++ VC4_REG32(SCALER6_DISP2_LPTRS), ++ VC4_REG32(SCALER6_DISP2_COB), ++ VC4_REG32(SCALER6_DISP2_STATUS), ++ VC4_REG32(SCALER6_DISP2_DL), ++ VC4_REG32(SCALER6_DISP2_RUN), ++ VC4_REG32(SCALER6_EOLN), ++ VC4_REG32(SCALER6_DL_STATUS), ++ VC4_REG32(SCALER6_BFG_MISC), ++ VC4_REG32(SCALER6_QOS0), ++ VC4_REG32(SCALER6_PROF0), ++ VC4_REG32(SCALER6_QOS1), ++ VC4_REG32(SCALER6_PROF1), ++ VC4_REG32(SCALER6_QOS2), ++ VC4_REG32(SCALER6_PROF2), ++ VC4_REG32(SCALER6_PRI_MAP0), ++ VC4_REG32(SCALER6_PRI_MAP1), ++ VC4_REG32(SCALER6_HISTCTRL), ++ VC4_REG32(SCALER6_HISTBIN0), ++ VC4_REG32(SCALER6_HISTBIN1), ++ VC4_REG32(SCALER6_HISTBIN2), ++ VC4_REG32(SCALER6_HISTBIN3), ++ VC4_REG32(SCALER6_HISTBIN4), ++ VC4_REG32(SCALER6_HISTBIN5), ++ VC4_REG32(SCALER6_HISTBIN6), ++ VC4_REG32(SCALER6_HISTBIN7), ++ VC4_REG32(SCALER6_HDR_CFG_REMAP), ++ VC4_REG32(SCALER6_COL_SPACE), ++ VC4_REG32(SCALER6_HVS_ID), ++ VC4_REG32(SCALER6_CFC1), ++ VC4_REG32(SCALER6_DISP_UPM_ISO0), ++ VC4_REG32(SCALER6_DISP_UPM_ISO1), ++ VC4_REG32(SCALER6_DISP_UPM_ISO2), ++ VC4_REG32(SCALER6_DISP_LBM_ISO0), ++ VC4_REG32(SCALER6_DISP_LBM_ISO1), ++ VC4_REG32(SCALER6_DISP_LBM_ISO2), ++ VC4_REG32(SCALER6_DISP_COB_ISO0), ++ VC4_REG32(SCALER6_DISP_COB_ISO1), ++ VC4_REG32(SCALER6_DISP_COB_ISO2), ++ VC4_REG32(SCALER6_BAD_COB), ++ VC4_REG32(SCALER6_BAD_LBM), ++ VC4_REG32(SCALER6_BAD_UPM), ++ VC4_REG32(SCALER6_BAD_AXI), ++}; ++ + void vc4_hvs_dump_state(struct vc4_hvs *hvs) + { + struct drm_device *drm = &hvs->vc4->base; +@@ -145,6 +219,55 @@ static int vc4_hvs_debugfs_dlist(struct + return 0; + } + ++static int vc6_hvs_debugfs_dlist(struct seq_file *m, void *data) ++{ ++ struct drm_info_node *node = m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct drm_printer p = drm_seq_file_printer(m); ++ unsigned int dlist_mem_size = hvs->dlist_mem_size; ++ unsigned int next_entry_start; ++ unsigned int i; ++ ++ for (i = 0; i < SCALER_CHANNELS_COUNT; i++) { ++ unsigned int active_dlist, dispstat; ++ unsigned int j; ++ ++ dispstat = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(i)), ++ SCALER6_DISPX_STATUS_MODE); ++ if (dispstat == SCALER6_DISPX_STATUS_MODE_DISABLED || ++ dispstat == SCALER6_DISPX_STATUS_MODE_EOF) { ++ drm_printf(&p, "HVS chan %u disabled\n", i); ++ continue; ++ } ++ ++ drm_printf(&p, "HVS chan %u:\n", i); ++ ++ active_dlist = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_DL(i)), ++ SCALER6_DISPX_DL_LACT); ++ next_entry_start = 0; ++ ++ for (j = active_dlist; j < dlist_mem_size; j++) { ++ u32 dlist_word; ++ ++ dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); ++ drm_printf(&p, "dlist: %02d: 0x%08x\n", j, ++ dlist_word); ++ if (!next_entry_start || ++ next_entry_start == j) { ++ if (dlist_word & SCALER_CTL0_END) ++ break; ++ next_entry_start = j + ++ VC4_GET_FIELD(dlist_word, ++ SCALER_CTL0_SIZE); ++ } ++ } ++ } ++ ++ return 0; ++} ++ + static int vc5_hvs_debugfs_gamma(struct seq_file *m, void *data) + { + struct drm_info_node *node = m->private; +@@ -435,6 +558,10 @@ static void vc4_hvs_irq_enable_eof(struc + SCALER5_DISPCTRL_DSPEIEOF(channel)); + break; + ++ case VC4_GEN_6: ++ enable_irq(hvs->eof_irq[channel].desc); ++ break; ++ + default: + break; + } +@@ -463,6 +590,10 @@ static void vc4_hvs_irq_clear_eof(struct + ~SCALER5_DISPCTRL_DSPEIEOF(channel)); + break; + ++ case VC4_GEN_6: ++ disable_irq_nosync(hvs->eof_irq[channel].desc); ++ break; ++ + default: + break; + } +@@ -622,26 +753,32 @@ static void vc4_hvs_dlist_free_work(stru + + u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u8 field = 0; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return 0; + +- switch (fifo) { +- case 0: +- field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), +- SCALER_DISPSTAT1_FRCNT0); +- break; +- case 1: +- field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), +- SCALER_DISPSTAT1_FRCNT1); +- break; +- case 2: +- field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT2), +- SCALER_DISPSTAT2_FRCNT2); +- break; ++ if (vc4->gen >= VC4_GEN_6) { ++ field = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(fifo)), ++ SCALER6_DISPX_STATUS_FRCNT); ++ } else { ++ switch (fifo) { ++ case 0: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER_DISPSTAT1_FRCNT0); ++ break; ++ case 1: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER_DISPSTAT1_FRCNT1); ++ break; ++ case 2: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT2), ++ SCALER_DISPSTAT2_FRCNT2); ++ break; ++ } + } + + drm_dev_exit(idx); +@@ -708,6 +845,23 @@ int vc4_hvs_get_fifo_from_output(struct + default: + return -EPIPE; + } ++ ++ case VC4_GEN_6: ++ switch (output) { ++ case 0: ++ return 0; ++ ++ case 2: ++ return 2; ++ ++ case 1: ++ case 3: ++ case 4: ++ return 1; ++ ++ default: ++ return -EPIPE; ++ } + } + + return -EPIPE; +@@ -782,7 +936,41 @@ static int vc4_hvs_init_channel(struct v + return 0; + } + +-void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) ++static int vc6_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, ++ struct drm_display_mode *mode, bool oneshot) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; ++ struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); ++ unsigned int chan = vc4_crtc_state->assigned_channel; ++ bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; ++ u32 disp_ctrl1; ++ int idx; ++ ++ if (!drm_dev_enter(drm, &idx)) ++ return -ENODEV; ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), SCALER6_DISPX_CTRL0_RESET); ++ ++ disp_ctrl1 = HVS_READ(SCALER6_DISPX_CTRL1(chan)); ++ disp_ctrl1 &= ~SCALER6_DISPX_CTRL1_INTLACE; ++ HVS_WRITE(SCALER6_DISPX_CTRL1(chan), ++ disp_ctrl1 | (interlace ? SCALER6_DISPX_CTRL1_INTLACE : 0)); ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), ++ SCALER6_DISPX_CTRL0_ENB | ++ VC4_SET_FIELD(mode->hdisplay - 1, ++ SCALER6_DISPX_CTRL0_FWIDTH) | ++ (oneshot ? SCALER6_DISPX_CTRL0_ONESHOT : 0) | ++ VC4_SET_FIELD(mode->vdisplay - 1, ++ SCALER6_DISPX_CTRL0_LINES)); ++ ++ drm_dev_exit(idx); ++ ++ return 0; ++} ++ ++static void __vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) + { + struct drm_device *drm = &hvs->vc4->base; + int idx; +@@ -813,6 +1001,42 @@ out: + drm_dev_exit(idx); + } + ++static void __vc6_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; ++ int idx; ++ ++ if (!drm_dev_enter(drm, &idx)) ++ return; ++ ++ if (HVS_READ(SCALER6_DISPX_CTRL0(chan)) & SCALER6_DISPX_CTRL0_ENB) ++ goto out; ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), ++ HVS_READ(SCALER6_DISPX_CTRL0(chan)) | SCALER6_DISPX_CTRL0_RESET); ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), ++ HVS_READ(SCALER6_DISPX_CTRL0(chan)) & ~SCALER6_DISPX_CTRL0_ENB); ++ ++ WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(chan)), ++ SCALER6_DISPX_STATUS_MODE) != ++ SCALER6_DISPX_STATUS_MODE_DISABLED); ++ ++out: ++ drm_dev_exit(idx); ++} ++ ++void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ ++ if (vc4->gen >= VC4_GEN_6) ++ __vc6_hvs_stop_channel(hvs, chan); ++ else ++ __vc4_hvs_stop_channel(hvs, chan); ++} ++ + static int vc4_hvs_gamma_check(struct drm_crtc *crtc, + struct drm_atomic_state *state) + { +@@ -907,8 +1131,14 @@ static void vc4_hvs_install_dlist(struct + return; + + WARN_ON(!vc4_state->mm); +- HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), +- vc4_state->mm->mm_node.start); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ HVS_WRITE(SCALER6_DISPX_LPTRS(vc4_state->assigned_channel), ++ VC4_SET_FIELD(vc4_state->mm->mm_node.start, ++ SCALER6_DISPX_LPTRS_HEADE)); ++ else ++ HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), ++ vc4_state->mm->mm_node.start); + + drm_dev_exit(idx); + } +@@ -965,7 +1195,11 @@ void vc4_hvs_atomic_enable(struct drm_cr + + vc4_hvs_install_dlist(crtc); + vc4_hvs_update_dlist(crtc); +- vc4_hvs_init_channel(vc4->hvs, crtc, mode, oneshot); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ vc6_hvs_init_channel(vc4->hvs, crtc, mode, oneshot); ++ else ++ vc4_hvs_init_channel(vc4->hvs, crtc, mode, oneshot); + } + + void vc4_hvs_atomic_disable(struct drm_crtc *crtc, +@@ -1052,13 +1286,28 @@ void vc4_hvs_atomic_flush(struct drm_crt + WARN_ON(!vc4_state->mm); + WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm->mm_node.size); + +- if (enable_bg_fill) ++ if (enable_bg_fill) { + /* This sets a black background color fill, as is the case + * with other DRM drivers. + */ +- HVS_WRITE(SCALER_DISPBKGNDX(channel), +- HVS_READ(SCALER_DISPBKGNDX(channel)) | +- SCALER_DISPBKGND_FILL); ++ if (vc4->gen >= VC4_GEN_6) ++ HVS_WRITE(SCALER6_DISPX_CTRL1(channel), ++ HVS_READ(SCALER6_DISPX_CTRL1(channel)) | ++ SCALER6_DISPX_CTRL1_BGENB); ++ else ++ HVS_WRITE(SCALER_DISPBKGNDX(channel), ++ HVS_READ(SCALER_DISPBKGNDX(channel)) | ++ SCALER_DISPBKGND_FILL); ++ } else { ++ if (vc4->gen >= VC4_GEN_6) ++ HVS_WRITE(SCALER6_DISPX_CTRL1(channel), ++ HVS_READ(SCALER6_DISPX_CTRL1(channel)) & ++ ~SCALER6_DISPX_CTRL1_BGENB); ++ else ++ HVS_WRITE(SCALER_DISPBKGNDX(channel), ++ HVS_READ(SCALER_DISPBKGNDX(channel)) & ++ ~SCALER_DISPBKGND_FILL); ++ } + + /* Only update DISPLIST if the CRTC was already running and is not + * being disabled. +@@ -1210,6 +1459,27 @@ static irqreturn_t vc4_hvs_irq_handler(i + return irqret; + } + ++static irqreturn_t vc6_hvs_eof_irq_handler(int irq, void *data) ++{ ++ struct drm_device *dev = data; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_hvs *hvs = vc4->hvs; ++ unsigned int i; ++ ++ for (i = 0; i < HVS_NUM_CHANNELS; i++) { ++ if (!hvs->eof_irq[i].enabled) ++ continue; ++ ++ if (hvs->eof_irq[i].desc != irq) ++ continue; ++ ++ vc4_hvs_schedule_dlist_sweep(hvs, i); ++ return IRQ_HANDLED; ++ } ++ ++ return IRQ_NONE; ++} ++ + int vc4_hvs_debugfs_init(struct drm_minor *minor) + { + struct drm_device *drm = minor->dev; +@@ -1232,8 +1502,10 @@ int vc4_hvs_debugfs_init(struct drm_mino + NULL); + } + +- ret = vc4_debugfs_add_file(minor, "hvs_dlists", +- vc4_hvs_debugfs_dlist, NULL); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc4_debugfs_add_file(minor, "hvs_dlists", vc6_hvs_debugfs_dlist, NULL); ++ else ++ ret = vc4_debugfs_add_file(minor, "hvs_dlists", vc4_hvs_debugfs_dlist, NULL); + if (ret) + return ret; + +@@ -1256,6 +1528,9 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + { + struct drm_device *drm = &vc4->base; + struct vc4_hvs *hvs; ++ unsigned int dlist_start; ++ size_t dlist_size; ++ size_t lbm_size; + + hvs = drmm_kzalloc(drm, sizeof(*hvs), GFP_KERNEL); + if (!hvs) +@@ -1270,14 +1545,39 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + INIT_LIST_HEAD(&hvs->stale_dlist_entries); + INIT_WORK(&hvs->free_dlist_work, vc4_hvs_dlist_free_work); + +- /* Set up the HVS display list memory manager. We never +- * overwrite the setup from the bootloader (just 128b out of +- * our 16K), since we don't want to scramble the screen when +- * transitioning from the firmware's boot setup to runtime. +- */ +- drm_mm_init(&hvs->dlist_mm, +- HVS_BOOTLOADER_DLIST_END, +- (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END); ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ case VC4_GEN_5: ++ /* Set up the HVS display list memory manager. We never ++ * overwrite the setup from the bootloader (just 128b ++ * out of our 16K), since we don't want to scramble the ++ * screen when transitioning from the firmware's boot ++ * setup to runtime. ++ */ ++ dlist_start = HVS_BOOTLOADER_DLIST_END; ++ dlist_size = (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END; ++ break; ++ ++ case VC4_GEN_6: ++ dlist_start = HVS_BOOTLOADER_DLIST_END; ++ ++ /* ++ * If we are running a test, it means that we can't ++ * access a register. Use a plausible size then. ++ */ ++ if (!kunit_get_current_test()) ++ dlist_size = HVS_READ(SCALER6_CXM_SIZE); ++ else ++ dlist_size = 4096; ++ ++ break; ++ ++ default: ++ drm_err(drm, "Unknown VC4 generation: %d", vc4->gen); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ drm_mm_init(&hvs->dlist_mm, dlist_start, dlist_size); + + hvs->dlist_mem_size = dlist_size; + +@@ -1286,12 +1586,46 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + * between planes when they don't overlap on the screen, but + * for now we just allocate globally. + */ +- if (vc4->gen == VC4_GEN_4) ++ ++ switch (vc4->gen) { ++ case VC4_GEN_4: + /* 48k words of 2x12-bit pixels */ +- drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024); +- else ++ lbm_size = 48 * SZ_1K; ++ break; ++ ++ case VC4_GEN_5: + /* 60k words of 4x12-bit pixels */ +- drm_mm_init(&hvs->lbm_mm, 0, 60 * 1024); ++ lbm_size = 60 * SZ_1K; ++ break; ++ ++ case VC4_GEN_6: ++ /* ++ * If we are running a test, it means that we can't ++ * access a register. Use a plausible size then. ++ */ ++ lbm_size = 1024; ++ break; ++ ++ default: ++ drm_err(drm, "Unknown VC4 generation: %d", vc4->gen); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ drm_mm_init(&hvs->lbm_mm, 0, lbm_size); ++ ++ if (vc4->gen >= VC4_GEN_6) { ++ ida_init(&hvs->upm_handles); ++ ++ /* ++ * NOTE: On BCM2712, the size can also be read through ++ * the SCALER_UBM_SIZE register. We would need to do a ++ * register access though, which we can't do with kunit ++ * that also uses this function to create its mock ++ * device. ++ */ ++ drm_mm_init(&hvs->upm_mm, 0, 1024 * HVS_UBM_WORD_SIZE); ++ } ++ + + vc4->hvs = hvs; + +@@ -1388,10 +1722,124 @@ static int vc4_hvs_hw_init(struct vc4_hv + return 0; + } + ++#define CFC1_N_NL_CSC_CTRL(x) (0xa000 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C00(x) (0xa008 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C01(x) (0xa00c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C02(x) (0xa010 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C03(x) (0xa014 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C04(x) (0xa018 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C10(x) (0xa01c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C11(x) (0xa020 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C12(x) (0xa024 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C13(x) (0xa028 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C14(x) (0xa02c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C20(x) (0xa030 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C21(x) (0xa034 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C22(x) (0xa038 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C23(x) (0xa03c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C24(x) (0xa040 + ((x) * 0x3000)) ++ ++/* 4 S2.22 multiplication factors, and 1 S9.15 addititive element for each of 3 ++ * output components ++ */ ++struct vc6_csc_coeff_entry { ++ u32 csc[3][5]; ++}; ++ ++static const struct vc6_csc_coeff_entry csc_coeffs[2][3] = { ++ [DRM_COLOR_YCBCR_LIMITED_RANGE] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ .csc = { ++ { 0x004A8542, 0x0, 0x0066254A, 0x0, 0xFF908A0D }, ++ { 0x004A8542, 0xFFE6ED5D, 0xFFCBF856, 0x0, 0x0043C9A3 }, ++ { 0x004A8542, 0x00811A54, 0x0, 0x0, 0xFF759502 } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ .csc = { ++ { 0x004A8542, 0x0, 0x0072BC44, 0x0, 0xFF83F312 }, ++ { 0x004A8542, 0xFFF25A22, 0xFFDDE4D0, 0x0, 0x00267064 }, ++ { 0x004A8542, 0x00873197, 0x0, 0x0, 0xFF6F7DC0 } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ .csc = { ++ { 0x004A8542, 0x0, 0x006B4A17, 0x0, 0xFF8B653F }, ++ { 0x004A8542, 0xFFF402D9, 0xFFDDE4D0, 0x0, 0x0024C7AE }, ++ { 0x004A8542, 0x008912CC, 0x0, 0x0, 0xFF6D9C8B } ++ } ++ } ++ }, ++ [DRM_COLOR_YCBCR_FULL_RANGE] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ .csc = { ++ { 0x00400000, 0x0, 0x0059BA5E, 0x0, 0xFFA645A1 }, ++ { 0x00400000, 0xFFE9F9AC, 0xFFD24B97, 0x0, 0x0043BABB }, ++ { 0x00400000, 0x00716872, 0x0, 0x0, 0xFF8E978D } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ .csc = { ++ { 0x00400000, 0x0, 0x0064C985, 0x0, 0xFF9B367A }, ++ { 0x00400000, 0xFFF402E1, 0xFFE20A40, 0x0, 0x0029F2DE }, ++ { 0x00400000, 0x0076C226, 0x0, 0x0, 0xFF893DD9 } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ .csc = { ++ { 0x00400000, 0x0, 0x005E3F14, 0x0, 0xFFA1C0EB }, ++ { 0x00400000, 0xFFF577F6, 0xFFDB580F, 0x0, 0x002F2FFA }, ++ { 0x00400000, 0x007868DB, 0x0, 0x0, 0xFF879724 } ++ } ++ } ++ } ++}; ++ ++static int vc6_hvs_hw_init(struct vc4_hvs *hvs) ++{ ++ const struct vc6_csc_coeff_entry *coeffs; ++ unsigned int i; ++ ++ HVS_WRITE(SCALER6_CONTROL, ++ SCALER6_CONTROL_HVS_EN | ++ VC4_SET_FIELD(8, SCALER6_CONTROL_PF_LINES) | ++ VC4_SET_FIELD(15, SCALER6_CONTROL_MAX_REQS)); ++ ++ /* Set HVS arbiter priority to max */ ++ HVS_WRITE(SCALER6_PRI_MAP0, 0xffffffff); ++ HVS_WRITE(SCALER6_PRI_MAP1, 0xffffffff); ++ ++ for (i = 0; i < 6; i++) { ++ coeffs = &csc_coeffs[i / 3][i % 3]; ++ ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C00(i), coeffs->csc[0][0]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C01(i), coeffs->csc[0][1]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C02(i), coeffs->csc[0][2]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C03(i), coeffs->csc[0][3]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C04(i), coeffs->csc[0][4]); ++ ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C10(i), coeffs->csc[1][0]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C11(i), coeffs->csc[1][1]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C12(i), coeffs->csc[1][2]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C13(i), coeffs->csc[1][3]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C14(i), coeffs->csc[1][4]); ++ ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C20(i), coeffs->csc[2][0]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C21(i), coeffs->csc[2][1]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C22(i), coeffs->csc[2][2]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C23(i), coeffs->csc[2][3]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C24(i), coeffs->csc[2][4]); ++ ++ HVS_WRITE(CFC1_N_NL_CSC_CTRL(i), BIT(15)); ++ } ++ ++ return 0; ++} ++ + static int vc4_hvs_cob_init(struct vc4_hvs *hvs) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 reg, top; ++ u32 reg, top, base; + + /* + * Recompute Composite Output Buffer (COB) allocations for the +@@ -1452,6 +1900,31 @@ static int vc4_hvs_cob_init(struct vc4_h + HVS_WRITE(SCALER_DISPBASE0, reg); + break; + ++ case VC4_GEN_6: ++ #define VC6_COB_LINE_WIDTH 3840 ++ #define VC6_COB_NUM_LINES 4 ++ reg = 0; ++ top = 3840; ++ ++ HVS_WRITE(SCALER6_DISP2_COB, ++ VC4_SET_FIELD(top, SCALER6_DISPX_COB_TOP) | ++ VC4_SET_FIELD(base, SCALER6_DISPX_COB_BASE)); ++ ++ base = top + 16; ++ top += VC6_COB_LINE_WIDTH * VC6_COB_NUM_LINES; ++ ++ HVS_WRITE(SCALER6_DISP1_COB, ++ VC4_SET_FIELD(top, SCALER6_DISPX_COB_TOP) | ++ VC4_SET_FIELD(base, SCALER6_DISPX_COB_BASE)); ++ ++ base = top + 16; ++ top += VC6_COB_LINE_WIDTH * VC6_COB_NUM_LINES; ++ ++ HVS_WRITE(SCALER6_DISP0_COB, ++ VC4_SET_FIELD(top, SCALER6_DISPX_COB_TOP) | ++ VC4_SET_FIELD(base, SCALER6_DISPX_COB_BASE)); ++ break; ++ + default: + return -EINVAL; + } +@@ -1477,10 +1950,16 @@ static int vc4_hvs_bind(struct device *d + return PTR_ERR(hvs); + + hvs->regset.base = hvs->regs; +- hvs->regset.regs = vc4_hvs_regs; +- hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); + +- if (vc4->gen == VC4_GEN_5) { ++ if (vc4->gen >= VC4_GEN_6) { ++ hvs->regset.regs = vc6_hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(vc6_hvs_regs); ++ } else { ++ hvs->regset.regs = vc4_hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); ++ } ++ ++ if (vc4->gen >= VC4_GEN_5) { + struct rpi_firmware *firmware; + struct device_node *node; + unsigned int max_rate; +@@ -1494,12 +1973,20 @@ static int vc4_hvs_bind(struct device *d + if (!firmware) + return -EPROBE_DEFER; + +- hvs->core_clk = devm_clk_get(&pdev->dev, NULL); ++ hvs->core_clk = devm_clk_get(&pdev->dev, ++ (vc4->gen >= VC4_GEN_6) ? "core" : NULL); + if (IS_ERR(hvs->core_clk)) { + dev_err(&pdev->dev, "Couldn't get core clock\n"); + return PTR_ERR(hvs->core_clk); + } + ++ hvs->disp_clk = devm_clk_get(&pdev->dev, ++ (vc4->gen >= VC4_GEN_6) ? "disp" : NULL); ++ if (IS_ERR(hvs->disp_clk)) { ++ dev_err(&pdev->dev, "Couldn't get disp clock\n"); ++ return PTR_ERR(hvs->disp_clk); ++ } ++ + max_rate = rpi_firmware_clk_get_max_rate(firmware, + RPI_FIRMWARE_CORE_CLK_ID); + rpi_firmware_put(firmware); +@@ -1516,14 +2003,51 @@ static int vc4_hvs_bind(struct device *d + dev_err(&pdev->dev, "Couldn't enable the core clock\n"); + return ret; + } ++ ++ ret = clk_prepare_enable(hvs->disp_clk); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't enable the disp clock\n"); ++ return ret; ++ } + } + +- if (vc4->gen == VC4_GEN_4) +- hvs->dlist = hvs->regs + SCALER_DLIST_START; +- else ++ if (vc4->gen >= VC4_GEN_6) { ++ unsigned int i; ++ ++ for (i = 0; i < HVS_NUM_CHANNELS; i++) { ++ char irq_name[16]; ++ int irq; ++ ++ snprintf(irq_name, sizeof(irq_name), "ch%u-eof", i); ++ ++ irq = platform_get_irq_byname(pdev, irq_name); ++ if (irq < 0) { ++ dev_err(&pdev->dev, ++ "Couldn't get %s interrupt: %d\n", ++ irq_name, irq); ++ return irq; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, ++ irq, ++ vc6_hvs_eof_irq_handler, ++ IRQF_NO_AUTOEN, ++ dev_name(&pdev->dev), ++ drm); ++ ++ hvs->eof_irq[i].desc = irq; ++ } ++ } ++ ++ if (vc4->gen >= VC4_GEN_5) + hvs->dlist = hvs->regs + SCALER5_DLIST_START; ++ else ++ hvs->dlist = hvs->regs + SCALER_DLIST_START; + +- ret = vc4_hvs_hw_init(hvs); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc6_hvs_hw_init(hvs); ++ else ++ ret = vc4_hvs_hw_init(hvs); + if (ret) + return ret; + +@@ -1540,10 +2064,12 @@ static int vc4_hvs_bind(struct device *d + if (ret) + return ret; + +- ret = devm_request_irq(dev, platform_get_irq(pdev, 0), +- vc4_hvs_irq_handler, 0, "vc4 hvs", drm); +- if (ret) +- return ret; ++ if (vc4->gen < VC4_GEN_6) { ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_hvs_irq_handler, 0, "vc4 hvs", drm); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -1568,6 +2094,7 @@ static void vc4_hvs_unbind(struct device + drm_mm_remove_node(node); + drm_mm_takedown(&vc4->hvs->lbm_mm); + ++ clk_disable_unprepare(hvs->disp_clk); + clk_disable_unprepare(hvs->core_clk); + + vc4->hvs = NULL; +@@ -1591,6 +2118,7 @@ static int vc4_hvs_dev_remove(struct pla + + static const struct of_device_id vc4_hvs_dt_match[] = { + { .compatible = "brcm,bcm2711-hvs" }, ++ { .compatible = "brcm,bcm2712-hvs" }, + { .compatible = "brcm,bcm2835-hvs" }, + {} + }; +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -329,17 +329,59 @@ static void vc5_hvs_pv_muxing_commit(str + } + } + ++static void vc6_hvs_pv_muxing_commit(struct vc4_dev *vc4, ++ struct drm_atomic_state *state) ++{ ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct drm_crtc_state *crtc_state; ++ struct drm_crtc *crtc; ++ unsigned int i; ++ ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_6); ++ ++ for_each_new_crtc_in_state(state, crtc, crtc_state, i) { ++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); ++ struct vc4_encoder *vc4_encoder; ++ struct drm_encoder *encoder; ++ unsigned char mux; ++ u32 reg; ++ ++ if (!vc4_state->update_muxing) ++ continue; ++ ++ if (vc4_state->assigned_channel != 1) ++ continue; ++ ++ encoder = vc4_get_crtc_encoder(crtc, crtc_state); ++ vc4_encoder = to_vc4_encoder(encoder); ++ switch (vc4_encoder->type) { ++ case VC4_ENCODER_TYPE_HDMI1: ++ mux = 0; ++ break; ++ ++ case VC4_ENCODER_TYPE_TXP: ++ mux = 2; ++ break; ++ ++ default: ++ break; ++ } ++ ++ reg = HVS_READ(SCALER6_CONTROL); ++ HVS_WRITE(SCALER6_CONTROL, ++ (reg & ~SCALER6_CONTROL_DSP1_TARGET_MASK) | ++ VC4_SET_FIELD(mux, SCALER6_CONTROL_DSP1_TARGET)); ++ } ++} ++ + static void vc4_atomic_commit_tail(struct drm_atomic_state *state) + { + struct drm_device *dev = state->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; +- struct drm_crtc_state *new_crtc_state; + struct vc4_hvs_state *new_hvs_state; +- struct drm_crtc *crtc; + struct vc4_hvs_state *old_hvs_state; + unsigned int channel; +- int i; + + old_hvs_state = vc4_hvs_get_old_global_state(state); + if (WARN_ON(IS_ERR(old_hvs_state))) +@@ -349,14 +391,23 @@ static void vc4_atomic_commit_tail(struc + if (WARN_ON(IS_ERR(new_hvs_state))) + return; + +- for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { +- struct vc4_crtc_state *vc4_crtc_state; ++ if (vc4->gen < VC4_GEN_6) { ++ struct drm_crtc_state *new_crtc_state; ++ struct drm_crtc *crtc; ++ int i; ++ ++ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { ++ struct vc4_crtc_state *vc4_crtc_state; + +- if (!new_crtc_state->commit || vc4->firmware_kms) +- continue; ++ if (vc4->firmware_kms) ++ continue; + +- vc4_crtc_state = to_vc4_crtc_state(new_crtc_state); +- vc4_hvs_mask_underrun(hvs, vc4_crtc_state->assigned_channel); ++ if (!new_crtc_state->commit) ++ continue; ++ ++ vc4_crtc_state = to_vc4_crtc_state(new_crtc_state); ++ vc4_hvs_mask_underrun(hvs, vc4_crtc_state->assigned_channel); ++ } + } + + for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) { +@@ -378,7 +429,7 @@ static void vc4_atomic_commit_tail(struc + old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + +- if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long state_rate = max(old_hvs_state->core_clock_rate, + new_hvs_state->core_clock_rate); + unsigned long core_rate = clamp_t(unsigned long, state_rate, +@@ -391,17 +442,32 @@ static void vc4_atomic_commit_tail(struc + * modeset. + */ + WARN_ON(clk_set_min_rate(hvs->core_clk, core_rate)); ++ WARN_ON(clk_set_min_rate(hvs->disp_clk, core_rate)); + } + + drm_atomic_helper_commit_modeset_disables(dev, state); + +- vc4_ctm_commit(vc4, state); ++ if (vc4->gen <= VC4_GEN_5) ++ vc4_ctm_commit(vc4, state); + + if (!vc4->firmware_kms) { +- if (vc4->gen == VC4_GEN_5) +- vc5_hvs_pv_muxing_commit(vc4, state); +- else ++ switch (vc4->gen) { ++ case VC4_GEN_4: + vc4_hvs_pv_muxing_commit(vc4, state); ++ break; ++ ++ case VC4_GEN_5: ++ vc5_hvs_pv_muxing_commit(vc4, state); ++ break; ++ ++ case VC4_GEN_6: ++ vc6_hvs_pv_muxing_commit(vc4, state); ++ break; ++ ++ default: ++ drm_err(dev, "Unknown VC4 generation: %d", vc4->gen); ++ break; ++ } + } + + drm_atomic_helper_commit_planes(dev, state, +@@ -417,7 +483,7 @@ static void vc4_atomic_commit_tail(struc + + drm_atomic_helper_cleanup_planes(dev, state); + +- if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long core_rate = min_t(unsigned long, + hvs->max_core_rate, + new_hvs_state->core_clock_rate); +@@ -429,6 +495,7 @@ static void vc4_atomic_commit_tail(struc + * requirements. + */ + WARN_ON(clk_set_min_rate(hvs->core_clk, core_rate)); ++ WARN_ON(clk_set_min_rate(hvs->disp_clk, core_rate)); + + drm_dbg(dev, "Core clock actual rate: %lu Hz\n", + clk_get_rate(hvs->core_clk)); +@@ -1081,7 +1148,10 @@ int vc4_kms_load(struct drm_device *dev) + return ret; + } + +- if (vc4->gen == VC4_GEN_5) { ++ if (vc4->gen >= VC4_GEN_6) { ++ dev->mode_config.max_width = 8192; ++ dev->mode_config.max_height = 8192; ++ } else if (vc4->gen >= VC4_GEN_5) { + dev->mode_config.max_width = 7680; + dev->mode_config.max_height = 7680; + } else { +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -279,6 +279,7 @@ static bool plane_enabled(struct drm_pla + static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; ++ unsigned int i; + + if (WARN_ON(!plane->state)) + return NULL; +@@ -288,6 +289,11 @@ static struct drm_plane_state *vc4_plane + return NULL; + + memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm)); ++ memset(&vc4_state->upm, 0, sizeof(vc4_state->upm)); ++ ++ for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) ++ vc4_state->upm_handle[i] = 0; ++ + vc4_state->dlist_initialized = 0; + + __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base); +@@ -310,14 +316,30 @@ static void vc4_plane_destroy_state(stru + struct drm_plane_state *state) + { + struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ struct vc4_hvs *hvs = vc4->hvs; + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int i; + + if (drm_mm_node_allocated(&vc4_state->lbm)) { + unsigned long irqflags; + +- spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); ++ spin_lock_irqsave(&hvs->mm_lock, irqflags); + drm_mm_remove_node(&vc4_state->lbm); +- spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); ++ spin_unlock_irqrestore(&hvs->mm_lock, irqflags); ++ } ++ ++ for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) { ++ unsigned long irqflags; ++ ++ if (!drm_mm_node_allocated(&vc4_state->upm[i])) ++ continue; ++ ++ spin_lock_irqsave(&hvs->mm_lock, irqflags); ++ drm_mm_remove_node(&vc4_state->upm[i]); ++ spin_unlock_irqrestore(&hvs->mm_lock, irqflags); ++ ++ if (vc4_state->upm_handle[i] > 0) ++ ida_free(&hvs->upm_handles, vc4_state->upm_handle[i]); + } + + kfree(vc4_state->dlist); +@@ -543,6 +565,11 @@ static void vc4_write_tpz(struct vc4_pla + recip = ~0 / scale; + + vc4_dlist_write(vc4_state, ++ /* ++ * The BCM2712 is lacking BIT(31) compared to ++ * the previous generations, but we don't use ++ * it. ++ */ + VC4_SET_FIELD(scale, SCALER_TPZ0_SCALE) | + VC4_SET_FIELD(0, SCALER_TPZ0_IPHASE)); + vc4_dlist_write(vc4_state, +@@ -590,10 +617,15 @@ static void vc4_write_ppf(struct vc4_pla + vc4_dlist_write(vc4_state, + SCALER_PPF_AGC | + VC4_SET_FIELD(scale, SCALER_PPF_SCALE) | ++ /* ++ * The register layout documentation is slightly ++ * different to setup the phase in the BCM2712, ++ * but they seem equivalent. ++ */ + VC4_SET_FIELD(phase, SCALER_PPF_IPHASE)); + } + +-static u32 vc4_lbm_size(struct drm_plane_state *state) ++static u32 __vc4_lbm_size(struct drm_plane_state *state) + { + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); +@@ -641,6 +673,131 @@ static u32 vc4_lbm_size(struct drm_plane + return lbm; + } + ++static unsigned int vc4_lbm_words_per_component(const struct drm_plane_state *state, ++ unsigned int channel) ++{ ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ ++ switch (vc4_state->y_scaling[channel]) { ++ case VC4_SCALING_PPF: ++ return 4; ++ ++ case VC4_SCALING_TPZ: ++ return 2; ++ ++ default: ++ return 0; ++ } ++} ++ ++static unsigned int vc4_lbm_components(const struct drm_plane_state *state, ++ unsigned int channel) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ ++ if (vc4_state->y_scaling[channel] == VC4_SCALING_NONE) ++ return 0; ++ ++ if (info->is_yuv) ++ return channel ? 2 : 1; ++ ++ if (info->has_alpha) ++ return 4; ++ ++ return 3; ++} ++ ++static unsigned int vc4_lbm_channel_size(const struct drm_plane_state *state, ++ unsigned int channel) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int channels_scaled = 0; ++ unsigned int components, words, wpc; ++ unsigned int width, lines; ++ unsigned int i; ++ ++ /* LBM is meant to use the smaller of source or dest width, but there ++ * is a issue with UV scaling that the size required for the second ++ * channel is based on the source width only. ++ */ ++ if (info->hsub > 1 && channel == 1) ++ width = state->src_w >> 16; ++ else ++ width = min(state->src_w >> 16, state->crtc_w); ++ width = round_up(width / info->hsub, 4); ++ ++ wpc = vc4_lbm_words_per_component(state, channel); ++ if (!wpc) ++ return 0; ++ ++ components = vc4_lbm_components(state, channel); ++ if (!components) ++ return 0; ++ ++ if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) ++ components -= 1; ++ ++ words = width * wpc * components; ++ ++ lines = DIV_ROUND_UP(words, 128 / info->hsub); ++ ++ for (i = 0; i < 2; i++) ++ if (vc4_state->y_scaling[channel] != VC4_SCALING_NONE) ++ channels_scaled++; ++ ++ if (channels_scaled == 1) ++ lines = lines / 2; ++ ++ return lines; ++} ++ ++static unsigned int __vc6_lbm_size(const struct drm_plane_state *state) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ ++ if (info->hsub > 1) ++ return max(vc4_lbm_channel_size(state, 0), ++ vc4_lbm_channel_size(state, 1)); ++ else ++ return vc4_lbm_channel_size(state, 0); ++} ++ ++u32 vc4_lbm_size(struct drm_plane_state *state) ++{ ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); ++ ++ /* LBM is not needed when there's no vertical scaling. */ ++ if (vc4_state->y_scaling[0] == VC4_SCALING_NONE && ++ vc4_state->y_scaling[1] == VC4_SCALING_NONE) ++ return 0; ++ ++ if (vc4->gen >= VC4_GEN_6) ++ return __vc6_lbm_size(state); ++ else ++ return __vc4_lbm_size(state); ++} ++ ++static size_t vc6_upm_size(const struct drm_plane_state *state, ++ unsigned int plane) ++{ ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int stride = state->fb->pitches[plane]; ++ ++ /* ++ * TODO: This only works for raster formats, and is sub-optimal ++ * for buffers with a stride aligned on 32 bytes. ++ */ ++ unsigned int words_per_line = (stride + 62) / 32; ++ unsigned int fetch_region_size = words_per_line * 32; ++ unsigned int buffer_lines = 2 << vc4_state->upm_buffer_lines; ++ unsigned int buffer_size = fetch_region_size * buffer_lines; ++ ++ return ALIGN(buffer_size, HVS_UBM_WORD_SIZE); ++} ++ + static void vc4_write_scaling_parameters(struct drm_plane_state *state, + int channel) + { +@@ -744,6 +901,10 @@ static int vc4_plane_allocate_lbm(struct + if (!lbm_size) + return 0; + ++ /* ++ * NOTE: BCM2712 doesn't need to be aligned, since the size ++ * returned by vc4_lbm_size() is in words already. ++ */ + if (vc4->gen == VC4_GEN_5) + lbm_size = ALIGN(lbm_size, 64); + else if (vc4->gen == VC4_GEN_4) +@@ -781,6 +942,57 @@ static int vc4_plane_allocate_lbm(struct + return 0; + } + ++static int vc6_plane_allocate_upm(struct drm_plane_state *state) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ struct drm_device *drm = state->plane->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int i; ++ int ret; ++ ++ WARN_ON_ONCE(vc4->gen < VC4_GEN_6); ++ ++ vc4_state->upm_buffer_lines = SCALER6_PTR0_UPM_BUFF_SIZE_2_LINES; ++ ++ for (i = 0; i < info->num_planes; i++) { ++ unsigned long irqflags; ++ size_t upm_size; ++ ++ upm_size = vc6_upm_size(state, i); ++ if (!upm_size) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&hvs->mm_lock, irqflags); ++ ret = drm_mm_insert_node_generic(&hvs->upm_mm, ++ &vc4_state->upm[i], ++ upm_size, HVS_UBM_WORD_SIZE, ++ 0, 0); ++ spin_unlock_irqrestore(&hvs->mm_lock, irqflags); ++ if (ret) { ++ drm_err(drm, "Failed to allocate UPM entry: %d\n", ret); ++ return ret; ++ } ++ ++ ret = ida_alloc_range(&hvs->upm_handles, 1, 32, GFP_KERNEL); ++ if (ret < 0) ++ return ret; ++ ++ vc4_state->upm_handle[i] = ret; ++ ++ vc4_state->dlist[vc4_state->ptr0_offset[i]] |= ++ VC4_SET_FIELD(vc4_state->upm[i].start / HVS_UBM_WORD_SIZE, ++ SCALER6_PTR0_UPM_BASE) | ++ VC4_SET_FIELD(vc4_state->upm_handle[i] - 1, ++ SCALER6_PTR0_UPM_HANDLE) | ++ VC4_SET_FIELD(vc4_state->upm_buffer_lines, ++ SCALER6_PTR0_UPM_BUFF_SIZE); ++ } ++ ++ return 0; ++} ++ + /* + * The colorspace conversion matrices are held in 3 entries in the dlist. + * Create an array of them, with entries for each full and limited mode, and +@@ -1355,6 +1567,413 @@ static int vc4_plane_mode_set(struct drm + return 0; + } + ++static u32 vc6_plane_get_csc_mode(struct vc4_plane_state *vc4_state) ++{ ++ struct drm_plane_state *state = &vc4_state->base; ++ u32 ret = 0; ++ ++ if (vc4_state->is_yuv) { ++ enum drm_color_encoding color_encoding = state->color_encoding; ++ enum drm_color_range color_range = state->color_range; ++ ++ ret |= SCALER6_CTL2_CSC_ENABLE; ++ ++ /* CSC pre-loaded with: ++ * 0 = BT601 limited range ++ * 1 = BT709 limited range ++ * 2 = BT2020 limited range ++ * 3 = BT601 full range ++ * 4 = BT709 full range ++ * 5 = BT2020 full range ++ */ ++ if (color_encoding > DRM_COLOR_YCBCR_BT2020) ++ color_encoding = DRM_COLOR_YCBCR_BT601; ++ if (color_range > DRM_COLOR_YCBCR_FULL_RANGE) ++ color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; ++ ++ ret |= VC4_SET_FIELD(color_encoding + (color_range * 3), ++ SCALER6_CTL2_BRCM_CFC_CONTROL); ++ } ++ ++ return ret; ++} ++ ++static int vc6_plane_mode_set(struct drm_plane *plane, ++ struct drm_plane_state *state) ++{ ++ struct drm_device *drm = plane->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ struct drm_framebuffer *fb = state->fb; ++ const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); ++ u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); ++ int num_planes = fb->format->num_planes; ++ u32 h_subsample = fb->format->hsub; ++ u32 v_subsample = fb->format->vsub; ++ bool mix_plane_alpha; ++ bool covers_screen; ++ u32 scl0, scl1, pitch0; ++ u32 tiling, src_x, src_y; ++ u32 width, height; ++ u32 hvs_format = format->hvs; ++ u32 offsets[3] = { 0 }; ++ unsigned int rotation; ++ int ret, i; ++ ++ if (vc4_state->dlist_initialized) ++ return 0; ++ ++ ret = vc4_plane_setup_clipping_and_scaling(state); ++ if (ret) ++ return ret; ++ ++ width = vc4_state->src_w[0] >> 16; ++ height = vc4_state->src_h[0] >> 16; ++ ++ /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB ++ * and 4:4:4, scl1 should be set to scl0 so both channels of ++ * the scaler do the same thing. For YUV, the Y plane needs ++ * to be put in channel 1 and Cb/Cr in channel 0, so we swap ++ * the scl fields here. ++ */ ++ if (num_planes == 1) { ++ scl0 = vc4_get_scl_field(state, 0); ++ scl1 = scl0; ++ } else { ++ scl0 = vc4_get_scl_field(state, 1); ++ scl1 = vc4_get_scl_field(state, 0); ++ } ++ ++ rotation = drm_rotation_simplify(state->rotation, ++ DRM_MODE_ROTATE_0 | ++ DRM_MODE_REFLECT_X | ++ DRM_MODE_REFLECT_Y); ++ ++ /* We must point to the last line when Y reflection is enabled. */ ++ src_y = vc4_state->src_y >> 16; ++ if (rotation & DRM_MODE_REFLECT_Y) ++ src_y += height - 1; ++ ++ src_x = vc4_state->src_x >> 16; ++ ++ switch (base_format_mod) { ++ case DRM_FORMAT_MOD_LINEAR: ++ tiling = SCALER6_CTL0_ADDR_MODE_LINEAR; ++ ++ /* Adjust the base pointer to the first pixel to be scanned ++ * out. ++ */ ++ for (i = 0; i < num_planes; i++) { ++ offsets[i] += src_y / (i ? v_subsample : 1) * fb->pitches[i]; ++ offsets[i] += src_x / (i ? h_subsample : 1) * fb->format->cpp[i]; ++ } ++ ++ break; ++ ++ case DRM_FORMAT_MOD_BROADCOM_SAND128: ++ case DRM_FORMAT_MOD_BROADCOM_SAND256: { ++ uint32_t param = fourcc_mod_broadcom_param(fb->modifier); ++ u32 components_per_word; ++ u32 starting_offset; ++ u32 fetch_count; ++ ++ if (param > SCALER_TILE_HEIGHT_MASK) { ++ DRM_DEBUG_KMS("SAND height too large (%d)\n", ++ param); ++ return -EINVAL; ++ } ++ ++ if (fb->format->format == DRM_FORMAT_P030) { ++ hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; ++ tiling = SCALER6_CTL0_ADDR_MODE_128B; ++ } else { ++ hvs_format = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE; ++ ++ switch (base_format_mod) { ++ case DRM_FORMAT_MOD_BROADCOM_SAND128: ++ tiling = SCALER6_CTL0_ADDR_MODE_128B; ++ break; ++ case DRM_FORMAT_MOD_BROADCOM_SAND256: ++ tiling = SCALER6_CTL0_ADDR_MODE_256B; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* Adjust the base pointer to the first pixel to be scanned ++ * out. ++ * ++ * For P030, y_ptr [31:4] is the 128bit word for the start pixel ++ * y_ptr [3:0] is the pixel (0-11) contained within that 128bit ++ * word that should be taken as the first pixel. ++ * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the ++ * element within the 128bit word, eg for pixel 3 the value ++ * should be 6. ++ */ ++ for (i = 0; i < num_planes; i++) { ++ u32 tile_w, tile, x_off, pix_per_tile; ++ ++ if (fb->format->format == DRM_FORMAT_P030) { ++ /* ++ * Spec says: bits [31:4] of the given address ++ * should point to the 128-bit word containing ++ * the desired starting pixel, and bits[3:0] ++ * should be between 0 and 11, indicating which ++ * of the 12-pixels in that 128-bit word is the ++ * first pixel to be used ++ */ ++ u32 remaining_pixels = src_x % 96; ++ u32 aligned = remaining_pixels / 12; ++ u32 last_bits = remaining_pixels % 12; ++ ++ x_off = aligned * 16 + last_bits; ++ tile_w = 128; ++ pix_per_tile = 96; ++ } else { ++ switch (base_format_mod) { ++ case DRM_FORMAT_MOD_BROADCOM_SAND128: ++ tile_w = 128; ++ break; ++ case DRM_FORMAT_MOD_BROADCOM_SAND256: ++ tile_w = 256; ++ break; ++ default: ++ return -EINVAL; ++ } ++ pix_per_tile = tile_w / fb->format->cpp[0]; ++ x_off = (src_x % pix_per_tile) / ++ (i ? h_subsample : 1) * ++ fb->format->cpp[i]; ++ } ++ ++ tile = src_x / pix_per_tile; ++ ++ offsets[i] += param * tile_w * tile; ++ offsets[i] += src_y / (i ? v_subsample : 1) * tile_w; ++ offsets[i] += x_off & ~(i ? 1 : 0); ++ } ++ ++ components_per_word = fb->format->format == DRM_FORMAT_P030 ? 24 : 32; ++ starting_offset = src_x % components_per_word; ++ fetch_count = (width + starting_offset + components_per_word - 1) / ++ components_per_word; ++ ++ pitch0 = VC4_SET_FIELD(param, SCALER6_PTR2_PITCH) | ++ VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT); ++ break; ++ } ++ ++ default: ++ DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx", ++ (long long)fb->modifier); ++ return -EINVAL; ++ } ++ ++ /* fetch an extra pixel if we don't actually line up with the left edge. */ ++ if ((vc4_state->src_x & 0xffff) && vc4_state->src_x < (state->fb->width << 16)) ++ width++; ++ ++ /* same for the right side */ ++ if (((vc4_state->src_x + vc4_state->src_w[0]) & 0xffff) && ++ vc4_state->src_x + vc4_state->src_w[0] < (state->fb->width << 16)) ++ width++; ++ ++ /* now for the top */ ++ if ((vc4_state->src_y & 0xffff) && vc4_state->src_y < (state->fb->height << 16)) ++ height++; ++ ++ /* and the bottom */ ++ if (((vc4_state->src_y + vc4_state->src_h[0]) & 0xffff) && ++ vc4_state->src_y + vc4_state->src_h[0] < (state->fb->height << 16)) ++ height++; ++ ++ /* for YUV444 hardware wants double the width, otherwise it doesn't ++ * fetch full width of chroma ++ */ ++ if (format->drm == DRM_FORMAT_YUV444 || format->drm == DRM_FORMAT_YVU444) ++ width <<= 1; ++ ++ /* Don't waste cycles mixing with plane alpha if the set alpha ++ * is opaque or there is no per-pixel alpha information. ++ * In any case we use the alpha property value as the fixed alpha. ++ */ ++ mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && ++ fb->format->has_alpha; ++ ++ /* Control Word 0: Scaling Configuration & Element Validity*/ ++ vc4_dlist_write(vc4_state, ++ SCALER6_CTL0_VALID | ++ VC4_SET_FIELD(tiling, SCALER6_CTL0_ADDR_MODE) | ++ VC4_SET_FIELD(0, SCALER6_CTL0_ALPHA_MASK) | ++ (vc4_state->is_unity ? SCALER6_CTL0_UNITY : 0) | ++ VC4_SET_FIELD(format->pixel_order_hvs5, SCALER6_CTL0_ORDERRGBA) | ++ VC4_SET_FIELD(scl1, SCALER6_CTL0_SCL1_MODE) | ++ VC4_SET_FIELD(scl0, SCALER6_CTL0_SCL0_MODE) | ++ VC4_SET_FIELD(hvs_format, SCALER6_CTL0_PIXEL_FORMAT)); ++ ++ /* Position Word 0: Image Position */ ++ vc4_state->pos0_offset = vc4_state->dlist_count; ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(vc4_state->crtc_y, SCALER6_POS0_START_Y) | ++ (rotation & DRM_MODE_REFLECT_X ? SCALER6_POS0_HFLIP : 0) | ++ VC4_SET_FIELD(vc4_state->crtc_x, SCALER6_POS0_START_X)); ++ ++ /* Control Word 2: Alpha Value & CSC */ ++ vc4_dlist_write(vc4_state, ++ vc6_plane_get_csc_mode(vc4_state) | ++ vc4_hvs5_get_alpha_blend_mode(state) | ++ (mix_plane_alpha ? SCALER6_CTL2_ALPHA_MIX : 0) | ++ VC4_SET_FIELD(state->alpha >> 4, SCALER5_CTL2_ALPHA)); ++ ++ /* Position Word 1: Scaled Image Dimensions */ ++ if (!vc4_state->is_unity) ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(vc4_state->crtc_h - 1, ++ SCALER6_POS1_SCL_LINES) | ++ VC4_SET_FIELD(vc4_state->crtc_w - 1, ++ SCALER6_POS1_SCL_WIDTH)); ++ ++ /* Position Word 2: Source Image Size */ ++ vc4_state->pos2_offset = vc4_state->dlist_count; ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(height - 1, ++ SCALER6_POS2_SRC_LINES) | ++ VC4_SET_FIELD(width - 1, ++ SCALER6_POS2_SRC_WIDTH)); ++ ++ /* Position Word 3: Context */ ++ vc4_dlist_write(vc4_state, 0xc0c0c0c0); ++ ++ /* ++ * TODO: This only covers Raster Scan Order planes ++ */ ++ for (i = 0; i < num_planes; i++) { ++ dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); ++ ++ paddr += offsets[i]; ++ ++ /* Pointer Word 0 */ ++ vc4_state->ptr0_offset[i] = vc4_state->dlist_count; ++ vc4_dlist_write(vc4_state, ++ (rotation & DRM_MODE_REFLECT_Y ? SCALER6_PTR0_VFLIP : 0) | ++ /* ++ * The UPM buffer will be allocated in ++ * vc6_plane_allocate_upm(). ++ */ ++ VC4_SET_FIELD(upper_32_bits(paddr) & 0xf, ++ SCALER6_PTR0_UPPER_ADDR)); ++ ++ /* Pointer Word 1 */ ++ vc4_dlist_write(vc4_state, lower_32_bits(paddr)); ++ ++ /* Pointer Word 2 */ ++ if (base_format_mod != DRM_FORMAT_MOD_BROADCOM_SAND128 && ++ base_format_mod != DRM_FORMAT_MOD_BROADCOM_SAND256) { ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(fb->pitches[i], ++ SCALER6_PTR2_PITCH)); ++ } else { ++ vc4_dlist_write(vc4_state, pitch0); ++ } ++ } ++ ++ /* ++ * Palette Word 0 ++ * TODO: We're not using the palette mode ++ */ ++ ++ /* ++ * Trans Word 0 ++ * TODO: It's only relevant if we set the trans_rgb bit in the ++ * control word 0, and we don't at the moment. ++ */ ++ ++ vc4_state->lbm_offset = 0; ++ ++ if (!vc4_state->is_unity || fb->format->is_yuv) { ++ /* ++ * Reserve a slot for the LBM Base Address. The real value will ++ * be set when calling vc4_plane_allocate_lbm(). ++ */ ++ if (vc4_state->y_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[1] != VC4_SCALING_NONE) { ++ vc4_state->lbm_offset = vc4_state->dlist_count; ++ vc4_dlist_counter_increment(vc4_state); ++ } ++ ++ if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->x_scaling[1] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[1] != VC4_SCALING_NONE) { ++ if (num_planes > 1) ++ /* ++ * Emit Cb/Cr as channel 0 and Y as channel ++ * 1. This matches how we set up scl0/scl1 ++ * above. ++ */ ++ vc4_write_scaling_parameters(state, 1); ++ ++ vc4_write_scaling_parameters(state, 0); ++ } ++ ++ /* ++ * If any PPF setup was done, then all the kernel ++ * pointers get uploaded. ++ */ ++ if (vc4_state->x_scaling[0] == VC4_SCALING_PPF || ++ vc4_state->y_scaling[0] == VC4_SCALING_PPF || ++ vc4_state->x_scaling[1] == VC4_SCALING_PPF || ++ vc4_state->y_scaling[1] == VC4_SCALING_PPF) { ++ u32 kernel = ++ VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start, ++ SCALER_PPF_KERNEL_OFFSET); ++ ++ /* HPPF plane 0 */ ++ vc4_dlist_write(vc4_state, kernel); ++ /* VPPF plane 0 */ ++ vc4_dlist_write(vc4_state, kernel); ++ /* HPPF plane 1 */ ++ vc4_dlist_write(vc4_state, kernel); ++ /* VPPF plane 1 */ ++ vc4_dlist_write(vc4_state, kernel); ++ } ++ } ++ ++ vc4_dlist_write(vc4_state, SCALER6_CTL0_END); ++ ++ vc4_state->dlist[0] |= ++ VC4_SET_FIELD(vc4_state->dlist_count, SCALER6_CTL0_NEXT); ++ ++ /* crtc_* are already clipped coordinates. */ ++ covers_screen = vc4_state->crtc_x == 0 && vc4_state->crtc_y == 0 && ++ vc4_state->crtc_w == state->crtc->mode.hdisplay && ++ vc4_state->crtc_h == state->crtc->mode.vdisplay; ++ ++ /* ++ * Background fill might be necessary when the plane has per-pixel ++ * alpha content or a non-opaque plane alpha and could blend from the ++ * background or does not cover the entire screen. ++ */ ++ vc4_state->needs_bg_fill = fb->format->has_alpha || !covers_screen || ++ state->alpha != DRM_BLEND_ALPHA_OPAQUE; ++ ++ /* ++ * Flag the dlist as initialized to avoid checking it twice in case ++ * the async update check already called vc4_plane_mode_set() and ++ * decided to fallback to sync update because async update was not ++ * possible. ++ */ ++ vc4_state->dlist_initialized = 1; ++ ++ vc4_plane_calc_load(state); ++ ++ drm_dbg_driver(drm, "[PLANE:%d:%s] Computed DLIST size: %u\n", ++ plane->base.id, plane->name, vc4_state->dlist_count); ++ ++ return 0; ++} ++ + /* If a modeset involves changing the setup of a plane, the atomic + * infrastructure will call this to validate a proposed plane setup. + * However, if a plane isn't getting updated, this (and the +@@ -1365,6 +1984,7 @@ static int vc4_plane_mode_set(struct drm + static int vc4_plane_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) + { ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); + struct vc4_plane_state *vc4_state = to_vc4_plane_state(new_plane_state); +@@ -1375,7 +1995,10 @@ static int vc4_plane_atomic_check(struct + if (!plane_enabled(new_plane_state)) + return 0; + +- ret = vc4_plane_mode_set(plane, new_plane_state); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc6_plane_mode_set(plane, new_plane_state); ++ else ++ ret = vc4_plane_mode_set(plane, new_plane_state); + if (ret) + return ret; + +@@ -1383,6 +2006,12 @@ static int vc4_plane_atomic_check(struct + if (ret) + return ret; + ++ if (vc4->gen >= VC4_GEN_6) { ++ ret = vc6_plane_allocate_upm(new_plane_state); ++ if (ret) ++ return ret; ++ } ++ + return 0; + } + +@@ -1716,7 +2345,7 @@ struct drm_plane *vc4_plane_init(struct + }; + + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { +- if (!hvs_formats[i].hvs5_only || vc4->gen == VC4_GEN_5) { ++ if (!hvs_formats[i].hvs5_only || vc4->gen >= VC4_GEN_5) { + formats[num_formats] = hvs_formats[i].drm; + num_formats++; + } +@@ -1731,7 +2360,7 @@ struct drm_plane *vc4_plane_init(struct + return ERR_CAST(vc4_plane); + plane = &vc4_plane->base; + +- if (vc4->gen == VC4_GEN_5) ++ if (vc4->gen >= VC4_GEN_5) + drm_plane_helper_add(plane, &vc5_plane_helper_funcs); + else + drm_plane_helper_add(plane, &vc4_plane_helper_funcs); +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -536,6 +536,130 @@ + + #define SCALER5_DLIST_START 0x00004000 + ++#define SCALER6_VERSION 0x00000000 ++#define SCALER6_CXM_SIZE 0x00000004 ++#define SCALER6_LBM_SIZE 0x00000008 ++#define SCALER6_UBM_SIZE 0x0000000c ++#define SCALER6_COBA_SIZE 0x00000010 ++#define SCALER6_COB_SIZE 0x00000014 ++ ++#define SCALER6_CONTROL 0x00000020 ++# define SCALER6_CONTROL_HVS_EN BIT(31) ++# define SCALER6_CONTROL_PF_LINES_MASK VC4_MASK(22, 18) ++# define SCALER6_CONTROL_ABORT_ON_EMPTY BIT(16) ++# define SCALER6_CONTROL_DSP1_TARGET_MASK VC4_MASK(13, 12) ++# define SCALER6_CONTROL_MAX_REQS_MASK VC4_MASK(7, 4) ++ ++#define SCALER6_FETCHER_STATUS 0x00000024 ++#define SCALER6_FETCH_STATUS 0x00000028 ++#define SCALER6_HANDLE_ERROR 0x0000002c ++ ++#define SCALER6_DISP0_CTRL0 0x00000030 ++#define SCALER6_DISPX_CTRL0(x) \ ++ (SCALER6_DISP0_CTRL0 + ((x) * (SCALER6_DISP1_CTRL0 - SCALER6_DISP0_CTRL0))) ++# define SCALER6_DISPX_CTRL0_ENB BIT(31) ++# define SCALER6_DISPX_CTRL0_RESET BIT(30) ++# define SCALER6_DISPX_CTRL0_FWIDTH_MASK VC4_MASK(28, 16) ++# define SCALER6_DISPX_CTRL0_ONESHOT BIT(15) ++# define SCALER6_DISPX_CTRL0_ONECTX_MASK VC4_MASK(14, 13) ++# define SCALER6_DISPX_CTRL0_LINES_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_DISP0_CTRL1 0x00000034 ++#define SCALER6_DISPX_CTRL1(x) \ ++ (SCALER6_DISP0_CTRL1 + ((x) * (SCALER6_DISP1_CTRL1 - SCALER6_DISP0_CTRL1))) ++# define SCALER6_DISPX_CTRL1_BGENB BIT(8) ++# define SCALER6_DISPX_CTRL1_INTLACE BIT(0) ++ ++#define SCALER6_DISP0_BGND 0x00000038 ++#define SCALER6_DISPX_BGND(x) \ ++ (SCALER6_DISP0_BGND + ((x) * (SCALER6_DISP1_BGND - SCALER6_DISP0_BGND))) ++ ++#define SCALER6_DISP0_LPTRS 0x0000003c ++#define SCALER6_DISPX_LPTRS(x) \ ++ (SCALER6_DISP0_LPTRS + ((x) * (SCALER6_DISP1_LPTRS - SCALER6_DISP0_LPTRS))) ++# define SCALER6_DISPX_LPTRS_HEADE_MASK VC4_MASK(11, 0) ++ ++#define SCALER6_DISP0_COB 0x00000040 ++#define SCALER6_DISPX_COB(x) \ ++ (SCALER6_DISP0_COB + ((x) * (SCALER6_DISP1_COB - SCALER6_DISP0_COB))) ++# define SCALER6_DISPX_COB_TOP_MASK VC4_MASK(31, 16) ++# define SCALER6_DISPX_COB_BASE_MASK VC4_MASK(15, 0) ++ ++#define SCALER6_DISP0_STATUS 0x00000044 ++ ++#define SCALER6_DISPX_STATUS(x) \ ++ (SCALER6_DISP0_STATUS + ((x) * (SCALER6_DISP1_STATUS - SCALER6_DISP0_STATUS))) ++# define SCALER6_DISPX_STATUS_EMPTY BIT(22) ++# define SCALER6_DISPX_STATUS_FRCNT_MASK VC4_MASK(21, 16) ++# define SCALER6_DISPX_STATUS_OFIELD BIT(15) ++# define SCALER6_DISPX_STATUS_MODE_MASK VC4_MASK(14, 13) ++# define SCALER6_DISPX_STATUS_MODE_DISABLED 0 ++# define SCALER6_DISPX_STATUS_MODE_INIT 1 ++# define SCALER6_DISPX_STATUS_MODE_RUN 2 ++# define SCALER6_DISPX_STATUS_MODE_EOF 3 ++# define SCALER6_DISPX_STATUS_YLINE_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_DISP0_DL 0x00000048 ++ ++#define SCALER6_DISPX_DL(x) \ ++ (SCALER6_DISP0_DL + ((x) * (SCALER6_DISP1_DL - SCALER6_DISP0_DL))) ++# define SCALER6_DISPX_DL_LACT_MASK VC4_MASK(11, 0) ++ ++#define SCALER6_DISP0_RUN 0x0000004c ++#define SCALER6_DISP1_CTRL0 0x00000050 ++#define SCALER6_DISP1_CTRL1 0x00000054 ++#define SCALER6_DISP1_BGND 0x00000058 ++#define SCALER6_DISP1_LPTRS 0x0000005c ++#define SCALER6_DISP1_COB 0x00000060 ++#define SCALER6_DISP1_STATUS 0x00000064 ++#define SCALER6_DISP1_DL 0x00000068 ++#define SCALER6_DISP1_RUN 0x0000006c ++#define SCALER6_DISP2_CTRL0 0x00000070 ++#define SCALER6_DISP2_CTRL1 0x00000074 ++#define SCALER6_DISP2_BGND 0x00000078 ++#define SCALER6_DISP2_LPTRS 0x0000007c ++#define SCALER6_DISP2_COB 0x00000080 ++#define SCALER6_DISP2_STATUS 0x00000084 ++#define SCALER6_DISP2_DL 0x00000088 ++#define SCALER6_DISP2_RUN 0x0000008c ++#define SCALER6_EOLN 0x00000090 ++#define SCALER6_DL_STATUS 0x00000094 ++#define SCALER6_BFG_MISC 0x0000009c ++#define SCALER6_QOS0 0x000000a0 ++#define SCALER6_PROF0 0x000000a4 ++#define SCALER6_QOS1 0x000000a8 ++#define SCALER6_PROF1 0x000000ac ++#define SCALER6_QOS2 0x000000b0 ++#define SCALER6_PROF2 0x000000b4 ++#define SCALER6_PRI_MAP0 0x000000b8 ++#define SCALER6_PRI_MAP1 0x000000bc ++#define SCALER6_HISTCTRL 0x000000c0 ++#define SCALER6_HISTBIN0 0x000000c4 ++#define SCALER6_HISTBIN1 0x000000c8 ++#define SCALER6_HISTBIN2 0x000000cc ++#define SCALER6_HISTBIN3 0x000000d0 ++#define SCALER6_HISTBIN4 0x000000d4 ++#define SCALER6_HISTBIN5 0x000000d8 ++#define SCALER6_HISTBIN6 0x000000dc ++#define SCALER6_HISTBIN7 0x000000e0 ++#define SCALER6_HDR_CFG_REMAP 0x000000f4 ++#define SCALER6_COL_SPACE 0x000000f8 ++#define SCALER6_HVS_ID 0x000000fc ++#define SCALER6_CFC1 0x00000100 ++#define SCALER6_DISP_UPM_ISO0 0x00000200 ++#define SCALER6_DISP_UPM_ISO1 0x00000204 ++#define SCALER6_DISP_UPM_ISO2 0x00000208 ++#define SCALER6_DISP_LBM_ISO0 0x0000020c ++#define SCALER6_DISP_LBM_ISO1 0x00000210 ++#define SCALER6_DISP_LBM_ISO2 0x00000214 ++#define SCALER6_DISP_COB_ISO0 0x00000218 ++#define SCALER6_DISP_COB_ISO1 0x0000021c ++#define SCALER6_DISP_COB_ISO2 0x00000220 ++#define SCALER6_BAD_COB 0x00000224 ++#define SCALER6_BAD_LBM 0x00000228 ++#define SCALER6_BAD_UPM 0x0000022c ++#define SCALER6_BAD_AXI 0x00000230 ++ + # define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1) + # define VC4_HDMI_SW_RESET_HDMI BIT(0) + +@@ -1131,4 +1255,61 @@ enum hvs_pixel_format { + #define SCALER_PITCH0_TILE_WIDTH_R_MASK VC4_MASK(6, 0) + #define SCALER_PITCH0_TILE_WIDTH_R_SHIFT 0 + ++#define SCALER6_CTL0_END BIT(31) ++#define SCALER6_CTL0_VALID BIT(30) ++#define SCALER6_CTL0_NEXT_MASK VC4_MASK(29, 24) ++#define SCALER6_CTL0_RGB_TRANS BIT(23) ++#define SCALER6_CTL0_ADDR_MODE_MASK VC4_MASK(22, 20) ++#define SCALER6_CTL0_ADDR_MODE_LINEAR 0 ++#define SCALER6_CTL0_ADDR_MODE_128B 1 ++#define SCALER6_CTL0_ADDR_MODE_256B 2 ++#define SCALER6_CTL0_ADDR_MODE_MAP8 3 ++#define SCALER6_CTL0_ADDR_MODE_UIF 4 ++ ++#define SCALER6_CTL0_ALPHA_MASK_MASK VC4_MASK(19, 18) ++#define SCALER6_CTL0_UNITY BIT(15) ++#define SCALER6_CTL0_ORDERRGBA_MASK VC4_MASK(14, 13) ++#define SCALER6_CTL0_SCL1_MODE_MASK VC4_MASK(10, 8) ++#define SCALER6_CTL0_SCL0_MODE_MASK VC4_MASK(7, 5) ++#define SCALER6_CTL0_PIXEL_FORMAT_MASK VC4_MASK(4, 0) ++ ++#define SCALER6_POS0_START_Y_MASK VC4_MASK(28, 16) ++#define SCALER6_POS0_HFLIP BIT(15) ++#define SCALER6_POS0_START_X_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_CTL2_ALPHA_MODE_MASK VC4_MASK(31, 30) ++#define SCALER6_CTL2_ALPHA_PREMULT BIT(29) ++#define SCALER6_CTL2_ALPHA_MIX BIT(28) ++#define SCALER6_CTL2_BFG BIT(26) ++#define SCALER6_CTL2_CSC_ENABLE BIT(25) ++#define SCALER6_CTL2_BRCM_CFC_CONTROL_MASK VC4_MASK(18, 16) ++#define SCALER6_CTL2_ALPHA_MASK VC4_MASK(15, 4) ++ ++#define SCALER6_POS1_SCL_LINES_MASK VC4_MASK(28, 16) ++#define SCALER6_POS1_SCL_WIDTH_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_POS2_SRC_LINES_MASK VC4_MASK(28, 16) ++#define SCALER6_POS2_SRC_WIDTH_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_PTR0_VFLIP BIT(31) ++#define SCALER6_PTR0_UPM_BASE_MASK VC4_MASK(28, 16) ++#define SCALER6_PTR0_UPM_HANDLE_MASK VC4_MASK(14, 10) ++#define SCALER6_PTR0_UPM_BUFF_SIZE_MASK VC4_MASK(9, 8) ++#define SCALER6_PTR0_UPM_BUFF_SIZE_16_LINES 3 ++#define SCALER6_PTR0_UPM_BUFF_SIZE_8_LINES 2 ++#define SCALER6_PTR0_UPM_BUFF_SIZE_4_LINES 1 ++#define SCALER6_PTR0_UPM_BUFF_SIZE_2_LINES 0 ++#define SCALER6_PTR0_UPPER_ADDR_MASK VC4_MASK(7, 0) ++ ++#define SCALER6_PTR2_ALPHA_BPP_MASK VC4_MASK(31, 31) ++#define SCALER6_PTR2_ALPHA_BPP_1BPP 1 ++#define SCALER6_PTR2_ALPHA_BPP_8BPP 0 ++#define SCALER6_PTR2_ALPHA_ORDER_MASK VC4_MASK(30, 30) ++#define SCALER6_PTR2_ALPHA_ORDER_MSB_TO_LSB 1 ++#define SCALER6_PTR2_ALPHA_ORDER_LSB_TO_MSB 0 ++#define SCALER6_PTR2_ALPHA_OFFS_MASK VC4_MASK(29, 27) ++#define SCALER6_PTR2_LSKIP_MASK VC4_MASK(26, 24) ++#define SCALER6_PTR2_PITCH_MASK VC4_MASK(16, 0) ++#define SCALER6_PTR2_FETCH_COUNT_MASK VC4_MASK(26, 16) ++ + #endif /* VC4_REGS_H */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0964-drm-vc4-crtc-Add-support-for-BCM2712-PixelValves.patch b/target/linux/bcm27xx/patches-6.1/950-0964-drm-vc4-crtc-Add-support-for-BCM2712-PixelValves.patch new file mode 100644 index 0000000000..1870158e06 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0964-drm-vc4-crtc-Add-support-for-BCM2712-PixelValves.patch @@ -0,0 +1,144 @@ +From 000f1b7d4dc5b515c755ee25db301e26bded00e1 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:33:23 +0100 +Subject: [PATCH] drm/vc4: crtc: Add support for BCM2712 PixelValves + +The PixelValves found on the BCM2712 are similar to the ones found in +the previous generation. + +Compared to BCM2711, the pixelvalves only drive one HDMI controller each +and HDMI1 PixelValve has a FIFO long enough to support 4k at 60Hz. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 53 ++++++++++++++++++++++++++++++++-- + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ + drivers/gpu/drm/vc4/vc4_regs.h | 5 ++++ + 3 files changed, 58 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -239,6 +239,11 @@ static u32 vc4_get_fifo_full_level(struc + const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); + const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); + struct vc4_dev *vc4 = to_vc4_dev(vc4_crtc->base.dev); ++ ++ /* ++ * NOTE: Could we use register 0x68 (PV_HW_CFG1) to get the FIFO ++ * size? ++ */ + u32 fifo_len_bytes = pv_data->fifo_depth; + + /* +@@ -393,6 +398,12 @@ static void vc4_crtc_config_pv(struct dr + + vc4_crtc_pixelvalve_reset(crtc); + ++ /* ++ * NOTE: The BCM2712 has a H_OTE (Horizontal Odd Timing Enable) ++ * bit that, when set, will allow to specify the timings in ++ * pixels instead of cycles, thus allowing to specify odd ++ * timings. ++ */ + CRTC_WRITE(PV_HORZA, + VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc, + PV_HORZA_HBP) | +@@ -462,11 +473,17 @@ static void vc4_crtc_config_pv(struct dr + if (is_dsi) + CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); + +- if (vc4->gen == VC4_GEN_5) ++ if (vc4->gen >= VC4_GEN_5) + CRTC_WRITE(PV_MUX_CFG, + VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP, + PV_MUX_CFG_RGB_PIXEL_MUX_MODE)); + ++ if (vc4->gen >= VC4_GEN_6) ++ CRTC_WRITE(PV_PIPE_INIT_CTRL, ++ VC4_SET_FIELD(1, PV_PIPE_INIT_CTRL_PV_INIT_WIDTH) | ++ VC4_SET_FIELD(1, PV_PIPE_INIT_CTRL_PV_INIT_IDLE) | ++ PV_PIPE_INIT_CTRL_PV_INIT_EN); ++ + CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | + vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) | + VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | +@@ -565,7 +582,11 @@ int vc4_crtc_disable_at_boot(struct drm_ + if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node, + "brcm,bcm2711-pixelvalve2") || + of_device_is_compatible(vc4_crtc->pdev->dev.of_node, +- "brcm,bcm2711-pixelvalve4"))) ++ "brcm,bcm2711-pixelvalve4") || ++ of_device_is_compatible(vc4_crtc->pdev->dev.of_node, ++ "brcm,bcm2712-pixelvalve0") || ++ of_device_is_compatible(vc4_crtc->pdev->dev.of_node, ++ "brcm,bcm2712-pixelvalve1"))) + return 0; + + if (!(CRTC_READ(PV_CONTROL) & PV_CONTROL_EN)) +@@ -1304,6 +1325,32 @@ const struct vc4_pv_data bcm2711_pv4_dat + }, + }; + ++const struct vc4_pv_data bcm2712_pv0_data = { ++ .base = { ++ .debugfs_name = "crtc0_regs", ++ .hvs_available_channels = BIT(0), ++ .hvs_output = 0, ++ }, ++ .fifo_depth = 64, ++ .pixels_per_clock = 2, ++ .encoder_types = { ++ [0] = VC4_ENCODER_TYPE_HDMI0, ++ }, ++}; ++ ++const struct vc4_pv_data bcm2712_pv1_data = { ++ .base = { ++ .debugfs_name = "crtc1_regs", ++ .hvs_available_channels = BIT(1), ++ .hvs_output = 1, ++ }, ++ .fifo_depth = 64, ++ .pixels_per_clock = 2, ++ .encoder_types = { ++ [0] = VC4_ENCODER_TYPE_HDMI1, ++ }, ++}; ++ + static const struct of_device_id vc4_crtc_dt_match[] = { + { .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data }, + { .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data }, +@@ -1313,6 +1360,8 @@ static const struct of_device_id vc4_crt + { .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data }, + { .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data }, + { .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data }, ++ { .compatible = "brcm,bcm2712-pixelvalve0", .data = &bcm2712_pv0_data }, ++ { .compatible = "brcm,bcm2712-pixelvalve1", .data = &bcm2712_pv1_data }, + {} + }; + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -583,6 +583,8 @@ extern const struct vc4_pv_data bcm2711_ + extern const struct vc4_pv_data bcm2711_pv2_data; + extern const struct vc4_pv_data bcm2711_pv3_data; + extern const struct vc4_pv_data bcm2711_pv4_data; ++extern const struct vc4_pv_data bcm2712_pv0_data; ++extern const struct vc4_pv_data bcm2712_pv1_data; + + struct vc5_gamma_entry { + u32 x_c_terms; +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -215,6 +215,11 @@ + # define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_SHIFT 2 + # define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP 8 + ++#define PV_PIPE_INIT_CTRL 0x94 ++# define PV_PIPE_INIT_CTRL_PV_INIT_WIDTH_MASK VC4_MASK(11, 8) ++# define PV_PIPE_INIT_CTRL_PV_INIT_IDLE_MASK VC4_MASK(7, 4) ++# define PV_PIPE_INIT_CTRL_PV_INIT_EN BIT(0) ++ + #define SCALER_CHANNELS_COUNT 3 + + #define SCALER_DISPCTRL 0x00000000 diff --git a/target/linux/bcm27xx/patches-6.1/950-0965-drm-vc4-hdmi-Add-support-for-BCM2712-HDMI-controller.patch b/target/linux/bcm27xx/patches-6.1/950-0965-drm-vc4-hdmi-Add-support-for-BCM2712-HDMI-controller.patch new file mode 100644 index 0000000000..7cb4e5661d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0965-drm-vc4-hdmi-Add-support-for-BCM2712-HDMI-controller.patch @@ -0,0 +1,1057 @@ +From 1bb54596ae2a9a36f4aa9f8f2ba941320f463811 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:34:30 +0100 +Subject: [PATCH] drm/vc4: hdmi: Add support for BCM2712 HDMI controllers + +The HDMI controllers found in the BCM2712 are largely the ones found in +the BCM2711 with a different PHY. + +There's some difference with how timings are split between registers, +and HDMI1 is now able to run at 4k/60Hz. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 82 +++- + drivers/gpu/drm/vc4/vc4_hdmi.h | 4 + + drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 640 ++++++++++++++++++++++++++++ + drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 217 ++++++++++ + 4 files changed, 937 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -1127,6 +1127,7 @@ static void vc4_hdmi_encoder_post_crtc_d + { + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); + unsigned long flags; + int idx; + +@@ -1143,14 +1144,25 @@ static void vc4_hdmi_encoder_post_crtc_d + + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB); + ++ if (vc4->gen >= VC4_GEN_6) ++ HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | ++ VC4_HD_VID_CTL_BLANKPIX); ++ + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + mdelay(1); + +- spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); +- HDMI_WRITE(HDMI_VID_CTL, +- HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); +- spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ /* ++ * TODO: This should work on BCM2712, but doesn't for some ++ * reason and result in a system lockup. ++ */ ++ if (vc4->gen < VC4_GEN_6) { ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ HDMI_WRITE(HDMI_VID_CTL, ++ HDMI_READ(HDMI_VID_CTL) & ++ ~VC4_HD_VID_CTL_ENABLE); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ } + + vc4_hdmi_disable_scrambling(encoder); + +@@ -1757,7 +1769,6 @@ static void vc4_hdmi_encoder_pre_crtc_co + goto err_put_runtime_pm; + } + +- + vc4_hdmi_cec_update_clk_div(vc4_hdmi); + + if (tmds_char_rate > 297000000) +@@ -1862,6 +1873,7 @@ static void vc4_hdmi_encoder_post_crtc_e + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + + HDMI_WRITE(HDMI_VID_CTL, ++ HDMI_READ(HDMI_VID_CTL) | + VC4_HD_VID_CTL_ENABLE | + VC4_HD_VID_CTL_CLRRGB | + VC4_HD_VID_CTL_UNDERFLOW_ENABLE | +@@ -3796,7 +3808,9 @@ static int vc4_hdmi_bind(struct device * + return ret; + + if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || +- of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && ++ of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1") || ++ of_device_is_compatible(dev->of_node, "brcm,bcm2712-hdmi0") || ++ of_device_is_compatible(dev->of_node, "brcm,bcm2712-hdmi1")) && + HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) { + clk_prepare_enable(vc4_hdmi->pixel_clock); + clk_prepare_enable(vc4_hdmi->hsm_clock); +@@ -3931,10 +3945,66 @@ static const struct vc4_hdmi_variant bcm + .hp_detect = vc5_hdmi_hp_detect, + }; + ++static const struct vc4_hdmi_variant bcm2712_hdmi0_variant = { ++ .encoder_type = VC4_ENCODER_TYPE_HDMI0, ++ .debugfs_name = "hdmi0_regs", ++ .card_name = "vc4-hdmi-0", ++ .max_pixel_clock = 600000000, ++ .registers = vc6_hdmi_hdmi0_fields, ++ .num_registers = ARRAY_SIZE(vc6_hdmi_hdmi0_fields), ++ .phy_lane_mapping = { ++ PHY_LANE_0, ++ PHY_LANE_1, ++ PHY_LANE_2, ++ PHY_LANE_CK, ++ }, ++ .unsupported_odd_h_timings = true, ++ .external_irq_controller = true, ++ ++ .init_resources = vc5_hdmi_init_resources, ++ .csc_setup = vc5_hdmi_csc_setup, ++ .reset = vc5_hdmi_reset, ++ .set_timings = vc5_hdmi_set_timings, ++ .phy_init = vc6_hdmi_phy_init, ++ .phy_disable = vc6_hdmi_phy_disable, ++ .channel_map = vc5_hdmi_channel_map, ++ .supports_hdr = true, ++ .hp_detect = vc5_hdmi_hp_detect, ++}; ++ ++static const struct vc4_hdmi_variant bcm2712_hdmi1_variant = { ++ .encoder_type = VC4_ENCODER_TYPE_HDMI1, ++ .debugfs_name = "hdmi1_regs", ++ .card_name = "vc4-hdmi-1", ++ .max_pixel_clock = 600000000, ++ .registers = vc6_hdmi_hdmi1_fields, ++ .num_registers = ARRAY_SIZE(vc6_hdmi_hdmi1_fields), ++ .phy_lane_mapping = { ++ PHY_LANE_0, ++ PHY_LANE_1, ++ PHY_LANE_2, ++ PHY_LANE_CK, ++ }, ++ .unsupported_odd_h_timings = true, ++ .external_irq_controller = true, ++ ++ .init_resources = vc5_hdmi_init_resources, ++ .csc_setup = vc5_hdmi_csc_setup, ++ .reset = vc5_hdmi_reset, ++ .set_timings = vc5_hdmi_set_timings, ++ .phy_init = vc6_hdmi_phy_init, ++ .phy_disable = vc6_hdmi_phy_disable, ++ .channel_map = vc5_hdmi_channel_map, ++ .supports_hdr = true, ++ .hp_detect = vc5_hdmi_hp_detect, ++}; ++ + static const struct of_device_id vc4_hdmi_dt_match[] = { + { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant }, + { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant }, + { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant }, ++ { .compatible = "brcm,bcm2712-hdmi0", .data = &bcm2712_hdmi0_variant }, ++ { .compatible = "brcm,bcm2712-hdmi1", .data = &bcm2712_hdmi1_variant }, + {} + }; + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h +@@ -284,4 +284,8 @@ void vc5_hdmi_phy_disable(struct vc4_hdm + void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); + void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); + ++void vc6_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *vc4_conn_state); ++void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); ++ + #endif /* _VC4_HDMI_H_ */ +--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +@@ -125,6 +125,48 @@ + #define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT 24 + #define VC4_HDMI_RM_FORMAT_SHIFT_MASK VC4_MASK(25, 24) + ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BG_PWRUP BIT(8) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_LDO_PWRUP BIT(7) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BIAS_PWRUP BIT(6) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_RNDGEN_PWRUP BIT(4) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_CK_PWRUP BIT(3) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_2_PWRUP BIT(2) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_1_PWRUP BIT(1) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_0_PWRUP BIT(0) ++ ++#define VC6_HDMI_TX_PHY_PLL_REFCLK_REFCLK_SEL_CMOS BIT(13) ++#define VC6_HDMI_TX_PHY_PLL_REFCLK_REFFRQ_MASK VC4_MASK(9, 0) ++ ++#define VC6_HDMI_TX_PHY_PLL_POST_KDIV_CLK0_SEL_MASK VC4_MASK(3, 2) ++#define VC6_HDMI_TX_PHY_PLL_POST_KDIV_KDIV_MASK VC4_MASK(1, 0) ++ ++#define VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_EN BIT(10) ++#define VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_MASK VC4_MASK(9, 0) ++ ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL_MASK VC4_MASK(31, 28) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE_MASK VC4_MASK(27, 27) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL_MASK VC4_MASK(26, 26) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN_MASK VC4_MASK(25, 25) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL_MASK VC4_MASK(24, 23) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN_MASK VC4_MASK(22, 22) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL_MASK VC4_MASK(21, 21) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN_MASK VC4_MASK(20, 20) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL_MASK VC4_MASK(19, 18) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN_MASK VC4_MASK(17, 17) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN_MASK VC4_MASK(16, 16) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL_MASK VC4_MASK(15, 12) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN_MASK VC4_MASK(11, 11) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT_MASK VC4_MASK(10, 8) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT_MASK VC4_MASK(7, 5) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING_MASK VC4_MASK(4, 3) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING_MASK VC4_MASK(2, 1) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN_MASK VC4_MASK(0, 0) ++ ++#define VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_PLLPOST_RESETB BIT(1) ++#define VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB BIT(0) ++ ++#define VC6_HDMI_TX_PHY_PLL_POWERUP_CTL_PLL_PWRUP BIT(0) ++ + #define OSCILLATOR_FREQUENCY 54000000 + + void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, +@@ -558,3 +600,601 @@ void vc5_hdmi_phy_rng_disable(struct vc4 + VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } ++ ++#define VC6_VCO_MIN_FREQ (8ULL * 1000 * 1000 * 1000) ++#define VC6_VCO_MAX_FREQ (12ULL * 1000 * 1000 * 1000) ++ ++static unsigned long long ++vc6_phy_get_vco_freq(unsigned long long tmds_rate, unsigned int *vco_div) ++{ ++ unsigned int min_div; ++ unsigned int max_div; ++ unsigned int div; ++ ++ div = 0; ++ while (tmds_rate * div * 10 < VC6_VCO_MIN_FREQ) ++ div++; ++ min_div = div; ++ ++ while (tmds_rate * (div + 1) * 10 < VC6_VCO_MAX_FREQ) ++ div++; ++ max_div = div; ++ ++ div = min_div + (max_div - min_div) / 2; ++ ++ *vco_div = div; ++ return tmds_rate * div * 10; ++} ++ ++struct vc6_phy_lane_settings { ++ unsigned int ext_current_ctl:4; ++ unsigned int ffe_enable:1; ++ unsigned int slew_rate_ctl:1; ++ unsigned int ffe_post_tap_en:1; ++ unsigned int ldmos_bias_ctl:2; ++ unsigned int com_mode_ldmos_en:1; ++ unsigned int edge_sel:1; ++ unsigned int ext_current_src_hs_en:1; ++ unsigned int term_ctl:2; ++ unsigned int ext_current_src_en:1; ++ unsigned int int_current_src_en:1; ++ unsigned int int_current_ctl:4; ++ unsigned int int_current_src_hs_en:1; ++ unsigned int main_tap_current_select:3; ++ unsigned int post_tap_current_select:3; ++ unsigned int slew_ctl_slow_loading:2; ++ unsigned int slew_ctl_slow_driving:2; ++ unsigned int ffe_pre_tap_en:1; ++}; ++ ++struct vc6_phy_settings { ++ unsigned long long min_rate; ++ unsigned long long max_rate; ++ struct vc6_phy_lane_settings channel[3]; ++ struct vc6_phy_lane_settings clock; ++}; ++ ++static const struct vc6_phy_settings vc6_hdmi_phy_settings[] = { ++ { ++ 0, 222000000, ++ { ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++ { ++ 222000001, 297000000, ++ { ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ }, ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ }, ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ }, ++ }, ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* Internal Current Source Half Swing Enable*/ ++ .int_current_src_hs_en = 1, ++ }, ++ }, ++ { ++ 297000001, 597000044, ++ { ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* External Current Source Half Swing Enable*/ ++ .ext_current_src_hs_en = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* Internal Current Source Half Swing Enable*/ ++ .int_current_src_hs_en = 1, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++}; ++ ++static const struct vc6_phy_settings * ++vc6_phy_get_settings(unsigned long long tmds_rate) ++{ ++ unsigned int count = ARRAY_SIZE(vc6_hdmi_phy_settings); ++ unsigned int i; ++ ++ for (i = 0; i < count; i++) { ++ const struct vc6_phy_settings *s = &vc6_hdmi_phy_settings[i]; ++ ++ if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate) ++ return s; ++ } ++ ++ /* ++ * If the pixel clock exceeds our max setting, try the max ++ * setting anyway. ++ */ ++ return &vc6_hdmi_phy_settings[count - 1]; ++} ++ ++static const struct vc6_phy_lane_settings * ++vc6_phy_get_channel_settings(enum vc4_hdmi_phy_channel chan, ++ unsigned long long tmds_rate) ++{ ++ const struct vc6_phy_settings *settings = vc6_phy_get_settings(tmds_rate); ++ ++ if (chan == PHY_LANE_CK) ++ return &settings->clock; ++ ++ return &settings->channel[chan]; ++} ++ ++static void vc6_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) ++{ ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ ++ HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); ++ HDMI_WRITE(HDMI_TX_PHY_POWERUP_CTL, 0); ++} ++ ++void vc6_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *conn_state) ++{ ++ const struct vc6_phy_lane_settings *chan0_settings; ++ const struct vc6_phy_lane_settings *chan1_settings; ++ const struct vc6_phy_lane_settings *chan2_settings; ++ const struct vc6_phy_lane_settings *clock_settings; ++ const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; ++ unsigned long long pixel_freq = conn_state->tmds_char_rate; ++ unsigned long long vco_freq; ++ unsigned char word_sel; ++ unsigned long flags; ++ unsigned int vco_div; ++ ++ vco_freq = vc6_phy_get_vco_freq(pixel_freq, &vco_div); ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ ++ vc6_hdmi_reset_phy(vc4_hdmi); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_0, 0x810c6000); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_1, 0x00b8c451); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_2, 0x46402e31); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_3, 0x00b8c005); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_4, 0x42410261); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_5, 0xcc021001); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_6, 0xc8301c80); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_7, 0xb0804444); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_8, 0xf80f8000); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_REFCLK, ++ VC6_HDMI_TX_PHY_PLL_REFCLK_REFCLK_SEL_CMOS | ++ VC4_SET_FIELD(54, VC6_HDMI_TX_PHY_PLL_REFCLK_REFFRQ)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x7f); ++ ++ HDMI_WRITE(HDMI_RM_OFFSET, ++ VC4_HDMI_RM_OFFSET_ONLY | ++ VC4_SET_FIELD(phy_get_rm_offset(vco_freq), ++ VC4_HDMI_RM_OFFSET_OFFSET)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_VCOCLK_DIV, ++ VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_EN | ++ VC4_SET_FIELD(vco_div, ++ VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_CFG, ++ VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CFG_PDIV)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_POST_KDIV, ++ VC4_SET_FIELD(2, VC6_HDMI_TX_PHY_PLL_POST_KDIV_CLK0_SEL) | ++ VC4_SET_FIELD(1, VC6_HDMI_TX_PHY_PLL_POST_KDIV_KDIV)); ++ ++ chan0_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_0, ++ VC4_SET_FIELD(chan0_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan0_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(chan0_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(chan0_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(chan0_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(chan0_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(chan0_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(chan0_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan0_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(chan0_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan0_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan0_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan0_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan0_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan0_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan0_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(chan0_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(chan0_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ chan1_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_1, ++ VC4_SET_FIELD(chan1_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan1_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(chan1_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(chan1_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(chan1_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(chan1_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(chan1_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(chan1_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan1_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(chan1_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan1_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan1_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan1_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan1_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan1_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan1_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(chan1_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(chan1_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ chan2_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_2, ++ VC4_SET_FIELD(chan2_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan2_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(chan2_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(chan2_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(chan2_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(chan2_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(chan2_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(chan2_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan2_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(chan2_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan2_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan2_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan2_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan2_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan2_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan2_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(chan2_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(chan2_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ clock_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_CK, ++ VC4_SET_FIELD(clock_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(clock_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(clock_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(clock_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(clock_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(clock_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(clock_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(clock_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(clock_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(clock_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(clock_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(clock_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(clock_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(clock_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(clock_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(clock_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(clock_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(clock_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ if (pixel_freq >= 340000000) ++ word_sel = 3; ++ else ++ word_sel = 0; ++ HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel); ++ ++ HDMI_WRITE(HDMI_TX_PHY_POWERUP_CTL, ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BG_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_LDO_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BIAS_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_CK_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_2_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_1_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_0_PWRUP); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_POWERUP_CTL, ++ VC6_HDMI_TX_PHY_PLL_POWERUP_CTL_PLL_PWRUP); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_RESET_CTL, ++ HDMI_READ(HDMI_TX_PHY_PLL_RESET_CTL) & ++ ~VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_RESET_CTL, ++ HDMI_READ(HDMI_TX_PHY_PLL_RESET_CTL) | ++ VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++} ++ ++void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) ++{ ++} +--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +@@ -111,13 +111,30 @@ enum vc4_hdmi_field { + HDMI_TX_PHY_CTL_1, + HDMI_TX_PHY_CTL_2, + HDMI_TX_PHY_CTL_3, ++ HDMI_TX_PHY_CTL_CK, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, + HDMI_TX_PHY_PLL_CFG, ++ HDMI_TX_PHY_PLL_CFG_PDIV, + HDMI_TX_PHY_PLL_CTL_0, + HDMI_TX_PHY_PLL_CTL_1, ++ HDMI_TX_PHY_PLL_MISC_0, ++ HDMI_TX_PHY_PLL_MISC_1, ++ HDMI_TX_PHY_PLL_MISC_2, ++ HDMI_TX_PHY_PLL_MISC_3, ++ HDMI_TX_PHY_PLL_MISC_4, ++ HDMI_TX_PHY_PLL_MISC_5, ++ HDMI_TX_PHY_PLL_MISC_6, ++ HDMI_TX_PHY_PLL_MISC_7, ++ HDMI_TX_PHY_PLL_MISC_8, ++ HDMI_TX_PHY_PLL_POST_KDIV, ++ HDMI_TX_PHY_PLL_POWERUP_CTL, ++ HDMI_TX_PHY_PLL_REFCLK, ++ HDMI_TX_PHY_PLL_RESET_CTL, ++ HDMI_TX_PHY_PLL_VCOCLK_DIV, + HDMI_TX_PHY_POWERDOWN_CTL, ++ HDMI_TX_PHY_POWERUP_CTL, + HDMI_TX_PHY_RESET_CTL, + HDMI_TX_PHY_TMDS_CLK_WORD_SEL, + HDMI_VEC_INTERFACE_CFG, +@@ -383,6 +400,206 @@ static const struct vc4_hdmi_register __ + + VC5_RM_REG(HDMI_RM_CONTROL, 0x000), + VC5_RM_REG(HDMI_RM_OFFSET, 0x018), ++ VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), ++ ++ VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), ++ ++ VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), ++ ++ VC5_CSC_REG(HDMI_CSC_CTL, 0x000), ++ VC5_CSC_REG(HDMI_CSC_12_11, 0x004), ++ VC5_CSC_REG(HDMI_CSC_14_13, 0x008), ++ VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), ++ VC5_CSC_REG(HDMI_CSC_24_23, 0x010), ++ VC5_CSC_REG(HDMI_CSC_32_31, 0x014), ++ VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), ++}; ++ ++static const struct vc4_hdmi_register __maybe_unused vc6_hdmi_hdmi0_fields[] = { ++ VC4_HD_REG(HDMI_DVP_CTL, 0x0000), ++ VC4_HD_REG(HDMI_MAI_CTL, 0x0010), ++ VC4_HD_REG(HDMI_MAI_THR, 0x0014), ++ VC4_HD_REG(HDMI_MAI_FMT, 0x0018), ++ VC4_HD_REG(HDMI_MAI_DATA, 0x001c), ++ VC4_HD_REG(HDMI_MAI_SMP, 0x0020), ++ VC4_HD_REG(HDMI_VID_CTL, 0x0044), ++ VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060), ++ ++ VC4_HDMI_REG(HDMI_FIFO_CTL, 0x07c), ++ VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0c0), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0c4), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0cc), ++ VC4_HDMI_REG(HDMI_CRP_CFG, 0x0d0), ++ VC4_HDMI_REG(HDMI_CTS_0, 0x0d4), ++ VC4_HDMI_REG(HDMI_CTS_1, 0x0d8), ++ VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e8), ++ VC4_HDMI_REG(HDMI_HORZA, 0x0ec), ++ VC4_HDMI_REG(HDMI_HORZB, 0x0f0), ++ VC4_HDMI_REG(HDMI_VERTA0, 0x0f4), ++ VC4_HDMI_REG(HDMI_VERTB0, 0x0f8), ++ VC4_HDMI_REG(HDMI_VERTA1, 0x100), ++ VC4_HDMI_REG(HDMI_VERTB1, 0x104), ++ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x114), ++ VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0a4), ++ VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a8), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_1, 0x148), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_2, 0x14c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_3, 0x150), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_4, 0x158), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_5, 0x15c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_6, 0x160), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_7, 0x164), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_8, 0x168), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_9, 0x16c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_10, 0x170), ++ VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x18c), ++ VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x194), ++ VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x198), ++ VC4_HDMI_REG(HDMI_HOTPLUG, 0x1c8), ++ VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1e4), ++ ++ VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0f0), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f4), ++ ++ VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), ++ VC5_PHY_REG(HDMI_TX_PHY_POWERUP_CTL, 0x004), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_CK, 0x014), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_REFCLK, 0x01c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POST_KDIV, 0x028), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_VCOCLK_DIV, 0x02c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x044), ++ VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x054), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_0, 0x060), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_1, 0x064), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_2, 0x068), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_3, 0x06c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_4, 0x070), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_5, 0x074), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_6, 0x078), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_7, 0x07c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_8, 0x080), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_RESET_CTL, 0x190), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POWERUP_CTL, 0x194), ++ ++ VC5_RM_REG(HDMI_RM_CONTROL, 0x000), ++ VC5_RM_REG(HDMI_RM_OFFSET, 0x018), ++ VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), ++ ++ VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), ++ ++ VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), ++ ++ VC5_CSC_REG(HDMI_CSC_CTL, 0x000), ++ VC5_CSC_REG(HDMI_CSC_12_11, 0x004), ++ VC5_CSC_REG(HDMI_CSC_14_13, 0x008), ++ VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), ++ VC5_CSC_REG(HDMI_CSC_24_23, 0x010), ++ VC5_CSC_REG(HDMI_CSC_32_31, 0x014), ++ VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), ++}; ++ ++static const struct vc4_hdmi_register __maybe_unused vc6_hdmi_hdmi1_fields[] = { ++ VC4_HD_REG(HDMI_DVP_CTL, 0x0000), ++ VC4_HD_REG(HDMI_MAI_CTL, 0x0030), ++ VC4_HD_REG(HDMI_MAI_THR, 0x0034), ++ VC4_HD_REG(HDMI_MAI_FMT, 0x0038), ++ VC4_HD_REG(HDMI_MAI_DATA, 0x003c), ++ VC4_HD_REG(HDMI_MAI_SMP, 0x0040), ++ VC4_HD_REG(HDMI_VID_CTL, 0x0048), ++ VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064), ++ ++ VC4_HDMI_REG(HDMI_FIFO_CTL, 0x07c), ++ VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0c0), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0c4), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0cc), ++ VC4_HDMI_REG(HDMI_CRP_CFG, 0x0d0), ++ VC4_HDMI_REG(HDMI_CTS_0, 0x0d4), ++ VC4_HDMI_REG(HDMI_CTS_1, 0x0d8), ++ VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e8), ++ VC4_HDMI_REG(HDMI_HORZA, 0x0ec), ++ VC4_HDMI_REG(HDMI_HORZB, 0x0f0), ++ VC4_HDMI_REG(HDMI_VERTA0, 0x0f4), ++ VC4_HDMI_REG(HDMI_VERTB0, 0x0f8), ++ VC4_HDMI_REG(HDMI_VERTA1, 0x100), ++ VC4_HDMI_REG(HDMI_VERTB1, 0x104), ++ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x114), ++ VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0a4), ++ VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a8), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_1, 0x148), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_2, 0x14c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_3, 0x150), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_4, 0x158), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_5, 0x15c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_6, 0x160), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_7, 0x164), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_8, 0x168), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_9, 0x16c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_10, 0x170), ++ VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x18c), ++ VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x194), ++ VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x198), ++ VC4_HDMI_REG(HDMI_HOTPLUG, 0x1c8), ++ VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1e4), ++ ++ VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0f0), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f4), ++ ++ VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), ++ VC5_PHY_REG(HDMI_TX_PHY_POWERUP_CTL, 0x004), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_CK, 0x014), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_REFCLK, 0x01c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POST_KDIV, 0x028), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_VCOCLK_DIV, 0x02c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x044), ++ VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x054), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_0, 0x060), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_1, 0x064), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_2, 0x068), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_3, 0x06c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_4, 0x070), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_5, 0x074), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_6, 0x078), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_7, 0x07c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_8, 0x080), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_RESET_CTL, 0x190), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POWERUP_CTL, 0x194), ++ ++ VC5_RM_REG(HDMI_RM_CONTROL, 0x000), ++ VC5_RM_REG(HDMI_RM_OFFSET, 0x018), + VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), + + VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), diff --git a/target/linux/bcm27xx/patches-6.1/950-0966-drm-vc4-txp-Introduce-structure-to-deal-with-revisio.patch b/target/linux/bcm27xx/patches-6.1/950-0966-drm-vc4-txp-Introduce-structure-to-deal-with-revisio.patch new file mode 100644 index 0000000000..c54ab0d360 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0966-drm-vc4-txp-Introduce-structure-to-deal-with-revisio.patch @@ -0,0 +1,117 @@ +From a68e8ffc3314612b0d00d491c8cdd61ae1d9af4e Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 25 Apr 2023 10:12:32 +0200 +Subject: [PATCH] drm/vc4: txp: Introduce structure to deal with revision + differences + +The BCM2712 will have several TXP with small differences. Let's add a +structure tied to the compatible to deal with those differences. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++- + drivers/gpu/drm/vc4/vc4_txp.c | 23 ++++++++++++++++------- + 3 files changed, 23 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -51,7 +51,7 @@ struct vc4_mock_desc { + + static const struct vc4_mock_desc vc4_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data, ++ VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +@@ -77,7 +77,7 @@ static const struct vc4_mock_desc vc4_mo + + static const struct vc4_mock_desc vc5_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data, ++ VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -561,7 +561,11 @@ struct vc4_crtc_data { + int hvs_output; + }; + +-extern const struct vc4_crtc_data vc4_txp_crtc_data; ++struct vc4_txp_data { ++ struct vc4_crtc_data base; ++}; ++ ++extern const struct vc4_txp_data vc4_txp_data; + + struct vc4_pv_data { + struct vc4_crtc_data base; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -159,6 +159,7 @@ + + struct vc4_txp { + struct vc4_crtc base; ++ const struct vc4_txp_data *data; + + struct platform_device *pdev; + +@@ -488,17 +489,20 @@ static irqreturn_t vc4_txp_interrupt(int + return IRQ_HANDLED; + } + +-const struct vc4_crtc_data vc4_txp_crtc_data = { +- .name = "txp", +- .debugfs_name = "txp_regs", +- .hvs_available_channels = BIT(2), +- .hvs_output = 2, ++const struct vc4_txp_data vc4_txp_data = { ++ .base = { ++ .name = "txp", ++ .debugfs_name = "txp_regs", ++ .hvs_available_channels = BIT(2), ++ .hvs_output = 2, ++ }, + }; + + static int vc4_txp_bind(struct device *dev, struct device *master, void *data) + { + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = dev_get_drvdata(master); ++ const struct vc4_txp_data *txp_data; + struct vc4_encoder *vc4_encoder; + struct drm_encoder *encoder; + struct vc4_crtc *vc4_crtc; +@@ -513,6 +517,11 @@ static int vc4_txp_bind(struct device *d + if (!txp) + return -ENOMEM; + ++ txp_data = of_device_get_match_data(dev); ++ if (!txp_data) ++ return -ENODEV; ++ ++ txp->data = txp_data; + txp->pdev = pdev; + txp->regs = vc4_ioremap_regs(pdev, 0); + if (IS_ERR(txp->regs)) +@@ -523,7 +532,7 @@ static int vc4_txp_bind(struct device *d + vc4_crtc->regset.regs = txp_regs; + vc4_crtc->regset.nregs = ARRAY_SIZE(txp_regs); + +- ret = vc4_crtc_init(drm, pdev, vc4_crtc, &vc4_txp_crtc_data, ++ ret = vc4_crtc_init(drm, pdev, vc4_crtc, &txp_data->base, + &vc4_txp_crtc_funcs, &vc4_txp_crtc_helper_funcs, true); + if (ret) + return ret; +@@ -584,7 +593,7 @@ static int vc4_txp_remove(struct platfor + } + + static const struct of_device_id vc4_txp_dt_match[] = { +- { .compatible = "brcm,bcm2835-txp" }, ++ { .compatible = "brcm,bcm2835-txp", .data = &vc4_txp_data }, + { /* sentinel */ }, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0967-drm-vc4-txp-Rename-TXP-data-structure.patch b/target/linux/bcm27xx/patches-6.1/950-0967-drm-vc4-txp-Rename-TXP-data-structure.patch new file mode 100644 index 0000000000..9303f86734 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0967-drm-vc4-txp-Rename-TXP-data-structure.patch @@ -0,0 +1,66 @@ +From 7d345345b70f00bf4c673a68da7d1cf0faf5cc47 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 25 Apr 2023 10:21:53 +0200 +Subject: [PATCH] drm/vc4: txp: Rename TXP data structure + +The TXP data structure has a name too generic for the multiple variants +we'll have to support. Let's rename it to mention the SoC it applies to. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_drv.h | 2 +- + drivers/gpu/drm/vc4/vc4_txp.c | 4 ++-- + 3 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -51,7 +51,7 @@ struct vc4_mock_desc { + + static const struct vc4_mock_desc vc4_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, ++ VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +@@ -77,7 +77,7 @@ static const struct vc4_mock_desc vc4_mo + + static const struct vc4_mock_desc vc5_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, ++ VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -565,7 +565,7 @@ struct vc4_txp_data { + struct vc4_crtc_data base; + }; + +-extern const struct vc4_txp_data vc4_txp_data; ++extern const struct vc4_txp_data bcm2835_txp_data; + + struct vc4_pv_data { + struct vc4_crtc_data base; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -489,7 +489,7 @@ static irqreturn_t vc4_txp_interrupt(int + return IRQ_HANDLED; + } + +-const struct vc4_txp_data vc4_txp_data = { ++const struct vc4_txp_data bcm2835_txp_data = { + .base = { + .name = "txp", + .debugfs_name = "txp_regs", +@@ -593,7 +593,7 @@ static int vc4_txp_remove(struct platfor + } + + static const struct of_device_id vc4_txp_dt_match[] = { +- { .compatible = "brcm,bcm2835-txp", .data = &vc4_txp_data }, ++ { .compatible = "brcm,bcm2835-txp", .data = &bcm2835_txp_data }, + { /* sentinel */ }, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0968-drm-vc4-txp-Add-byte-enable-toggle-bit.patch b/target/linux/bcm27xx/patches-6.1/950-0968-drm-vc4-txp-Add-byte-enable-toggle-bit.patch new file mode 100644 index 0000000000..cea9062b19 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0968-drm-vc4-txp-Add-byte-enable-toggle-bit.patch @@ -0,0 +1,56 @@ +From e8dbad6d506b6fac992fdf74a7e3a66a38e554c3 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 09:30:33 +0200 +Subject: [PATCH] drm/vc4: txp: Add byte enable toggle bit + +The MOPLET doesn't have the BYTE_ENABLE field to set, but the TXP and +MOP do, so let's add a boolean to control whether or not we need to set +it. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -563,6 +563,7 @@ struct vc4_crtc_data { + + struct vc4_txp_data { + struct vc4_crtc_data base; ++ unsigned int has_byte_enable:1; + }; + + extern const struct vc4_txp_data bcm2835_txp_data; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -291,6 +291,7 @@ static void vc4_txp_connector_atomic_com + struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, + conn); + struct vc4_txp *txp = connector_to_vc4_txp(conn); ++ const struct vc4_txp_data *txp_data = txp->data; + struct drm_gem_dma_object *gem; + struct drm_display_mode *mode; + struct drm_framebuffer *fb; +@@ -313,9 +314,11 @@ static void vc4_txp_connector_atomic_com + return; + + ctrl = TXP_GO | TXP_EI | +- VC4_SET_FIELD(0xf, TXP_BYTE_ENABLE) | + VC4_SET_FIELD(txp_fmts[i], TXP_FORMAT); + ++ if (txp_data->has_byte_enable) ++ ctrl |= VC4_SET_FIELD(0xf, TXP_BYTE_ENABLE); ++ + if (fb->format->has_alpha) + ctrl |= TXP_ALPHA_ENABLE; + else +@@ -496,6 +499,7 @@ const struct vc4_txp_data bcm2835_txp_da + .hvs_available_channels = BIT(2), + .hvs_output = 2, + }, ++ .has_byte_enable = true, + }; + + static int vc4_txp_bind(struct device *dev, struct device *master, void *data) diff --git a/target/linux/bcm27xx/patches-6.1/950-0969-drm-vc4-txp-Add-horizontal-and-vertical-size-offset-.patch b/target/linux/bcm27xx/patches-6.1/950-0969-drm-vc4-txp-Add-horizontal-and-vertical-size-offset-.patch new file mode 100644 index 0000000000..290473e834 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0969-drm-vc4-txp-Add-horizontal-and-vertical-size-offset-.patch @@ -0,0 +1,59 @@ +From a51e4acdab01540e1006e43f38e5befb40002de0 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 09:47:54 +0200 +Subject: [PATCH] drm/vc4: txp: Add horizontal and vertical size offset toggle + bit + +The new writeback controllers that can be found on the BCM2712 require +to have their horizontal and vertical size reduced by one. + +Let's tie that behaviour to the compatible so we can support both the +new and old controllers. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 14 ++++++++++++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -564,6 +564,7 @@ struct vc4_crtc_data { + struct vc4_txp_data { + struct vc4_crtc_data base; + unsigned int has_byte_enable:1; ++ unsigned int size_minus_one:1; + }; + + extern const struct vc4_txp_data bcm2835_txp_data; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -295,6 +295,8 @@ static void vc4_txp_connector_atomic_com + struct drm_gem_dma_object *gem; + struct drm_display_mode *mode; + struct drm_framebuffer *fb; ++ unsigned int hdisplay; ++ unsigned int vdisplay; + u32 ctrl; + int idx; + int i; +@@ -334,9 +336,17 @@ static void vc4_txp_connector_atomic_com + gem = drm_fb_dma_get_gem_obj(fb, 0); + TXP_WRITE(TXP_DST_PTR, gem->dma_addr + fb->offsets[0]); + TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); ++ ++ hdisplay = mode->hdisplay ?: 1; ++ vdisplay = mode->vdisplay ?: 1; ++ if (txp_data->size_minus_one) { ++ hdisplay -= 1; ++ vdisplay -= 1; ++ } ++ + TXP_WRITE(TXP_DIM, +- VC4_SET_FIELD(mode->hdisplay, TXP_WIDTH) | +- VC4_SET_FIELD(mode->vdisplay, TXP_HEIGHT)); ++ VC4_SET_FIELD(hdisplay, TXP_WIDTH) | ++ VC4_SET_FIELD(vdisplay, TXP_HEIGHT)); + + TXP_WRITE(TXP_DST_CTRL, ctrl); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0970-drm-vc4-txp-Handle-40-bits-DMA-Addresses.patch b/target/linux/bcm27xx/patches-6.1/950-0970-drm-vc4-txp-Handle-40-bits-DMA-Addresses.patch new file mode 100644 index 0000000000..5d1fbcb119 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0970-drm-vc4-txp-Handle-40-bits-DMA-Addresses.patch @@ -0,0 +1,59 @@ +From ddb9aa80692ed5d35e4ee4688c36789620f78c5c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 17:47:11 +0200 +Subject: [PATCH] drm/vc4: txp: Handle 40-bits DMA Addresses + +The BCM2712 MOP and MOPLET can handle addresses larger than 32bits +through an extra register. We can easily support it and make it +conditional based on the compatible through a boolean in our variant +structure. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 10 +++++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -565,6 +565,7 @@ struct vc4_txp_data { + struct vc4_crtc_data base; + unsigned int has_byte_enable:1; + unsigned int size_minus_one:1; ++ unsigned int supports_40bit_addresses:1; + }; + + extern const struct vc4_txp_data bcm2835_txp_data; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -145,6 +145,8 @@ + /* Number of lines received and committed to memory. */ + #define TXP_PROGRESS 0x10 + ++#define TXP_DST_PTR_HIGH 0x1c ++ + #define TXP_READ(offset) \ + ({ \ + kunit_fail_current_test("Accessing a register in a unit test!\n"); \ +@@ -297,6 +299,7 @@ static void vc4_txp_connector_atomic_com + struct drm_framebuffer *fb; + unsigned int hdisplay; + unsigned int vdisplay; ++ dma_addr_t addr; + u32 ctrl; + int idx; + int i; +@@ -334,7 +337,12 @@ static void vc4_txp_connector_atomic_com + return; + + gem = drm_fb_dma_get_gem_obj(fb, 0); +- TXP_WRITE(TXP_DST_PTR, gem->dma_addr + fb->offsets[0]); ++ addr = gem->dma_addr + fb->offsets[0]; ++ TXP_WRITE(TXP_DST_PTR, lower_32_bits(addr)); ++ ++ if (txp_data->supports_40bit_addresses) ++ TXP_WRITE(TXP_DST_PTR_HIGH, upper_32_bits(addr) & 0xff); ++ + TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); + + hdisplay = mode->hdisplay ?: 1; diff --git a/target/linux/bcm27xx/patches-6.1/950-0971-drm-vc4-txp-Move-the-encoder-type-in-the-variant-str.patch b/target/linux/bcm27xx/patches-6.1/950-0971-drm-vc4-txp-Move-the-encoder-type-in-the-variant-str.patch new file mode 100644 index 0000000000..0445c4f509 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0971-drm-vc4-txp-Move-the-encoder-type-in-the-variant-str.patch @@ -0,0 +1,44 @@ +From 2e8f4fa23af4bb794e9b2284a53aa40bbfdd3cbb Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 11:26:10 +0200 +Subject: [PATCH] drm/vc4: txp: Move the encoder type in the variant structure + +We'll have multiple TXP instances in the BCM2712, so we can't use a +single encoder type anymore. Let's tie the encoder type to the +compatible. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -563,6 +563,7 @@ struct vc4_crtc_data { + + struct vc4_txp_data { + struct vc4_crtc_data base; ++ enum vc4_encoder_type encoder_type; + unsigned int has_byte_enable:1; + unsigned int size_minus_one:1; + unsigned int supports_40bit_addresses:1; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -517,6 +517,7 @@ const struct vc4_txp_data bcm2835_txp_da + .hvs_available_channels = BIT(2), + .hvs_output = 2, + }, ++ .encoder_type = VC4_ENCODER_TYPE_TXP, + .has_byte_enable = true, + }; + +@@ -560,7 +561,7 @@ static int vc4_txp_bind(struct device *d + return ret; + + vc4_encoder = &txp->encoder; +- txp->encoder.type = VC4_ENCODER_TYPE_TXP; ++ txp->encoder.type = txp_data->encoder_type; + + encoder = &vc4_encoder->base; + encoder->possible_crtcs = drm_crtc_mask(&vc4_crtc->base); diff --git a/target/linux/bcm27xx/patches-6.1/950-0972-drm-vc4-txp-Add-a-new-TXP-encoder-type.patch b/target/linux/bcm27xx/patches-6.1/950-0972-drm-vc4-txp-Add-a-new-TXP-encoder-type.patch new file mode 100644 index 0000000000..f832fc1ed5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0972-drm-vc4-txp-Add-a-new-TXP-encoder-type.patch @@ -0,0 +1,475 @@ +From 68a00ca7b1d7809ac7be736c02238c142e629127 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 11:49:28 +0200 +Subject: [PATCH] drm/vc4: txp: Add a new TXP encoder type + +Starting with BCM2712, we'll have a two TXP. Let's follow the HDMI +example and add two encoder types for TXP: TXP0 and TXP1. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 4 +- + .../gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 106 +++++++++--------- + drivers/gpu/drm/vc4/vc4_drv.h | 3 +- + drivers/gpu/drm/vc4/vc4_kms.c | 2 +- + drivers/gpu/drm/vc4/vc4_txp.c | 2 +- + 5 files changed, 59 insertions(+), 58 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -52,7 +52,7 @@ struct vc4_mock_desc { + static const struct vc4_mock_desc vc4_mock = + VC4_MOCK_DESC( + VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, +- VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP0, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), + VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv0_data, +@@ -78,7 +78,7 @@ static const struct vc4_mock_desc vc4_mo + static const struct vc4_mock_desc vc5_mock = + VC4_MOCK_DESC( + VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, +- VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP0, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), + VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv0_data, +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -91,7 +91,7 @@ static const struct encoder_constraint v + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 1), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1), +- ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 2), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 2), + }; + +@@ -99,7 +99,7 @@ static const struct encoder_constraint v + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1), +- ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 0, 2), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 0, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 0, 1, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0, 1, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2), +@@ -208,7 +208,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("1 output: DSI1", + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("1 output: TXP", +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: DSI0, HDMI0", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0), +@@ -220,7 +220,7 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: DSI0, TXP", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: DPI, HDMI0", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0), +@@ -232,19 +232,19 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: DPI, TXP", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: HDMI0, DSI1", + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: HDMI0, TXP", + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: VEC, DSI1", + VC4_ENCODER_TYPE_VEC, + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: VEC, TXP", + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0, +@@ -252,7 +252,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +@@ -260,7 +260,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0, +@@ -268,7 +268,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +@@ -276,7 +276,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + }; + + KUNIT_ARRAY_PARAM(vc4_test_pv_muxing, +@@ -288,7 +288,7 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_DSI0), + VC4_PV_MUXING_TEST("TXP/DSI1 Conflict", +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("HDMI0/VEC Conflict", + VC4_ENCODER_TYPE_HDMI0, +@@ -297,22 +297,22 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("More than 3 outputs: DPI, HDMI0, DSI1, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + }; + + KUNIT_ARRAY_PARAM(vc4_test_pv_muxing_invalid, +@@ -343,7 +343,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("2 outputs: DPI, TXP", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: DPI, VEC", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC), +@@ -361,7 +361,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("2 outputs: DSI0, TXP", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: DSI0, VEC", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC), +@@ -373,7 +373,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("2 outputs: DSI1, TXP", + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), +@@ -385,7 +385,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("2 outputs: HDMI0, TXP", + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1", + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), +@@ -394,14 +394,14 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("2 outputs: HDMI1, TXP", + VC4_ENCODER_TYPE_HDMI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: TXP, VEC", +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +@@ -416,15 +416,15 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, DSI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI0", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, +@@ -441,7 +441,7 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +@@ -456,15 +456,15 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, DSI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI0", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, +@@ -491,17 +491,17 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, +@@ -520,17 +520,17 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, DSI1, HDMI0, HDMI1", +@@ -541,19 +541,19 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0, HDMI1", +@@ -564,24 +564,24 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, +@@ -600,17 +600,17 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, DSI1, HDMI0, HDMI1", +@@ -621,19 +621,19 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0, HDMI1", +@@ -644,27 +644,27 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: VEC, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -511,7 +511,8 @@ enum vc4_encoder_type { + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_SMI, + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, ++ VC4_ENCODER_TYPE_TXP1, + }; + + struct vc4_encoder { +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -359,7 +359,7 @@ static void vc6_hvs_pv_muxing_commit(str + mux = 0; + break; + +- case VC4_ENCODER_TYPE_TXP: ++ case VC4_ENCODER_TYPE_TXP0: + mux = 2; + break; + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -517,7 +517,7 @@ const struct vc4_txp_data bcm2835_txp_da + .hvs_available_channels = BIT(2), + .hvs_output = 2, + }, +- .encoder_type = VC4_ENCODER_TYPE_TXP, ++ .encoder_type = VC4_ENCODER_TYPE_TXP0, + .has_byte_enable = true, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0973-drm-vc4-txp-Add-support-for-BCM2712-MOP.patch b/target/linux/bcm27xx/patches-6.1/950-0973-drm-vc4-txp-Add-support-for-BCM2712-MOP.patch new file mode 100644 index 0000000000..aec0753408 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0973-drm-vc4-txp-Add-support-for-BCM2712-MOP.patch @@ -0,0 +1,64 @@ +From 831c6e8c68a66678e8329a382823dc83c483dcc8 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 09:30:49 +0200 +Subject: [PATCH] drm/vc4: txp: Add support for BCM2712 MOP + +The BCM2712 has an evolution of what used to be called TXP in the +earlier SoCs, but is now called MOP. + +There's a few differences still, so we can add a new compatible to deal +with them easily. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_txp.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -388,6 +388,7 @@ static const struct drm_connector_funcs + static void vc4_txp_encoder_disable(struct drm_encoder *encoder) + { + struct drm_device *drm = encoder->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_txp *txp = encoder_to_vc4_txp(encoder); + int idx; + +@@ -406,7 +407,8 @@ static void vc4_txp_encoder_disable(stru + WARN_ON(TXP_READ(TXP_DST_CTRL) & TXP_BUSY); + } + +- TXP_WRITE(TXP_DST_CTRL, TXP_POWERDOWN); ++ if (vc4->gen < VC4_GEN_6) ++ TXP_WRITE(TXP_DST_CTRL, TXP_POWERDOWN); + + drm_dev_exit(idx); + } +@@ -510,6 +512,19 @@ static irqreturn_t vc4_txp_interrupt(int + return IRQ_HANDLED; + } + ++const struct vc4_txp_data bcm2712_mop_data = { ++ .base = { ++ .name = "mop", ++ .debugfs_name = "mop_regs", ++ .hvs_available_channels = BIT(2), ++ .hvs_output = 2, ++ }, ++ .encoder_type = VC4_ENCODER_TYPE_TXP0, ++ .has_byte_enable = true, ++ .size_minus_one = true, ++ .supports_40bit_addresses = true, ++}; ++ + const struct vc4_txp_data bcm2835_txp_data = { + .base = { + .name = "txp", +@@ -616,6 +631,7 @@ static int vc4_txp_remove(struct platfor + } + + static const struct of_device_id vc4_txp_dt_match[] = { ++ { .compatible = "brcm,bcm2712-mop", .data = &bcm2712_mop_data }, + { .compatible = "brcm,bcm2835-txp", .data = &bcm2835_txp_data }, + { /* sentinel */ }, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0974-drm-vc4-txp-Add-BCM2712-MOPLET-support.patch b/target/linux/bcm27xx/patches-6.1/950-0974-drm-vc4-txp-Add-BCM2712-MOPLET-support.patch new file mode 100644 index 0000000000..b2a28bd144 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0974-drm-vc4-txp-Add-BCM2712-MOPLET-support.patch @@ -0,0 +1,42 @@ +From b239fc6a68fea2b073c4cb48884fbb697014ac2b Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Mon, 20 Feb 2023 17:16:01 +0100 +Subject: [PATCH] drm/vc4: txp: Add BCM2712 MOPLET support + +The BCM2712 features a simpler TXP called MOPLET. Let's add support for +it. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_txp.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -525,6 +525,18 @@ const struct vc4_txp_data bcm2712_mop_da + .supports_40bit_addresses = true, + }; + ++const struct vc4_txp_data bcm2712_moplet_data = { ++ .base = { ++ .name = "moplet", ++ .debugfs_name = "moplet_regs", ++ .hvs_available_channels = BIT(1), ++ .hvs_output = 4, ++ }, ++ .encoder_type = VC4_ENCODER_TYPE_TXP1, ++ .size_minus_one = true, ++ .supports_40bit_addresses = true, ++}; ++ + const struct vc4_txp_data bcm2835_txp_data = { + .base = { + .name = "txp", +@@ -632,6 +644,7 @@ static int vc4_txp_remove(struct platfor + + static const struct of_device_id vc4_txp_dt_match[] = { + { .compatible = "brcm,bcm2712-mop", .data = &bcm2712_mop_data }, ++ { .compatible = "brcm,bcm2712-moplet", .data = &bcm2712_moplet_data }, + { .compatible = "brcm,bcm2835-txp", .data = &bcm2835_txp_data }, + { /* sentinel */ }, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0975-drm-vc4-Add-additional-warn_on.patch b/target/linux/bcm27xx/patches-6.1/950-0975-drm-vc4-Add-additional-warn_on.patch new file mode 100644 index 0000000000..0fc95e5f6b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0975-drm-vc4-Add-additional-warn_on.patch @@ -0,0 +1,240 @@ +From bb05ccd66342643b1cd9a0a48cec3ebdc3eed511 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 21 Feb 2023 14:38:32 +0100 +Subject: [PATCH] drm/vc4: Add additional warn_on + +Some code path in vc4 are conditional to a generation and cannot be +executed on others. Let's put a WARN_ON if that ever happens. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 32 ++++++++++++++++++++++++++++++-- + drivers/gpu/drm/vc4/vc4_kms.c | 6 ++++++ + drivers/gpu/drm/vc4/vc4_plane.c | 19 +++++++++++++++++++ + 3 files changed, 55 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -417,12 +417,15 @@ static int vc4_hvs_upload_linear_kernel( + static void vc4_hvs_lut_load(struct vc4_hvs *hvs, + struct vc4_crtc *vc4_crtc) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + struct drm_crtc *crtc = &vc4_crtc->base; + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); + int idx; + u32 i; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -758,6 +761,8 @@ u8 vc4_hvs_get_fifo_frame_count(struct v + u8 field = 0; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + if (!drm_dev_enter(drm, &idx)) + return 0; + +@@ -791,6 +796,8 @@ int vc4_hvs_get_fifo_from_output(struct + u32 reg; + int ret; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + switch (vc4->gen) { + case VC4_GEN_4: + return output; +@@ -880,6 +887,8 @@ static int vc4_hvs_init_channel(struct v + u32 dispctrl; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; + +@@ -947,6 +956,8 @@ static int vc6_hvs_init_channel(struct v + u32 disp_ctrl1; + int idx; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_6); ++ + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; + +@@ -972,9 +983,12 @@ static int vc6_hvs_init_channel(struct v + + static void __vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1007,6 +1021,8 @@ static void __vc6_hvs_stop_channel(struc + struct drm_device *drm = &vc4->base; + int idx; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_6); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1234,6 +1250,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + bool found = false; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + if (!drm_dev_enter(dev, &idx)) { + vc4_crtc_send_vblank(crtc); + return; +@@ -1324,6 +1342,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + if (crtc->state->color_mgmt_changed) { + u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(channel)); + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (crtc->state->gamma_lut) { + if (vc4->gen == VC4_GEN_4) { + vc4_hvs_update_gamma_lut(hvs, vc4_crtc); +@@ -1363,6 +1383,8 @@ void vc4_hvs_mask_underrun(struct vc4_hv + u32 dispctrl; + int idx; + ++ WARN_ON(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1383,6 +1405,8 @@ void vc4_hvs_unmask_underrun(struct vc4_ + u32 dispctrl; + int idx; + ++ WARN_ON(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1417,6 +1441,8 @@ static irqreturn_t vc4_hvs_irq_handler(i + u32 status; + u32 dspeislur; + ++ WARN_ON(vc4->gen > VC4_GEN_5); ++ + /* + * NOTE: We don't need to protect the register access using + * drm_dev_enter() there because the interrupt handler lifetime +@@ -1466,6 +1492,8 @@ static irqreturn_t vc6_hvs_eof_irq_handl + struct vc4_hvs *hvs = vc4->hvs; + unsigned int i; + ++ WARN_ON(vc4->gen < VC4_GEN_6); ++ + for (i = 0; i < HVS_NUM_CHANNELS; i++) { + if (!hvs->eof_irq[i].enabled) + continue; +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -147,6 +147,8 @@ vc4_ctm_commit(struct vc4_dev *vc4, stru + if (vc4->firmware_kms) + return; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (ctm_state->fifo) { + HVS_WRITE(SCALER_OLEDCOEF2, + VC4_SET_FIELD(vc4_ctm_s31_32_to_s0_9(ctm->matrix[0]), +@@ -222,6 +224,8 @@ static void vc4_hvs_pv_muxing_commit(str + struct drm_crtc *crtc; + unsigned int i; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_4); ++ + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); +@@ -265,6 +269,8 @@ static void vc5_hvs_pv_muxing_commit(str + unsigned int i; + u32 reg; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_5); ++ + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -555,8 +555,11 @@ static int vc4_plane_setup_clipping_and_ + + static void vc4_write_tpz(struct vc4_plane_state *vc4_state, u32 src, u32 dst) + { ++ struct vc4_dev *vc4 = to_vc4_dev(vc4_state->base.plane->dev); + u32 scale, recip; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + scale = src / dst; + + /* The specs note that while the reciprocal would be defined +@@ -581,10 +584,13 @@ static void vc4_write_tpz(struct vc4_pla + + static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst, u32 xy, int channel, int chroma_offset) + { ++ struct vc4_dev *vc4 = to_vc4_dev(vc4_state->base.plane->dev); + u32 scale = src / dst; + s32 offset, offset2; + s32 phase; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + /* Start the phase at 1/2 pixel from the 1st pixel at src_x. + 1/4 pixel for YUV, plus the offset for chroma siting */ + if (channel) { +@@ -801,8 +807,11 @@ static size_t vc6_upm_size(const struct + static void vc4_write_scaling_parameters(struct drm_plane_state *state, + int channel) + { ++ struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + /* Ch0 H-PPF Word 0: Scaling Parameters */ + if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) { + vc4_write_ppf(vc4_state, +@@ -1040,6 +1049,11 @@ static const u32 colorspace_coeffs[2][DR + + static u32 vc4_hvs4_get_alpha_blend_mode(struct drm_plane_state *state) + { ++ struct drm_device *dev = state->state->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_4); ++ + if (!state->fb->format->has_alpha) + return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED, + SCALER_POS2_ALPHA_MODE); +@@ -1061,6 +1075,11 @@ static u32 vc4_hvs4_get_alpha_blend_mode + + static u32 vc4_hvs5_get_alpha_blend_mode(struct drm_plane_state *state) + { ++ struct drm_device *dev = state->state->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_5 && vc4->gen != VC4_GEN_6); ++ + if (!state->fb->format->has_alpha) + return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED, + SCALER5_CTL2_ALPHA_MODE); diff --git a/target/linux/bcm27xx/patches-6.1/950-0976-drm-vc4-tests-Switch-generation-mockup-to-a-switch.patch b/target/linux/bcm27xx/patches-6.1/950-0976-drm-vc4-tests-Switch-generation-mockup-to-a-switch.patch new file mode 100644 index 0000000000..0751d46536 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0976-drm-vc4-tests-Switch-generation-mockup-to-a-switch.patch @@ -0,0 +1,47 @@ +From 336917ca87807b8a4bb08855b4dcb0477289c765 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:35:16 +0100 +Subject: [PATCH] drm/vc4: tests: Switch generation mockup to a switch + +Testing whether the VideoCore generation we want to mock is vc5 or vc4 +worked so far, but will be difficult to extend to support BCM2712 (VC6). + +Convert to a switch. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -155,13 +155,27 @@ static int __build_mock(struct kunit *te + + static struct vc4_dev *__mock_device(struct kunit *test, enum vc4_gen gen) + { ++ const struct vc4_mock_desc *desc; ++ const struct drm_driver *drv; + struct drm_device *drm; +- const struct drm_driver *drv = (gen == VC4_GEN_5) ? &vc5_drm_driver : &vc4_drm_driver; +- const struct vc4_mock_desc *desc = (gen == VC4_GEN_5) ? &vc5_mock : &vc4_mock; + struct vc4_dev *vc4; + struct device *dev; + int ret; + ++ switch (gen) { ++ case VC4_GEN_4: ++ drv = &vc4_drm_driver; ++ desc = &vc4_mock; ++ break; ++ case VC4_GEN_5: ++ drv = &vc5_drm_driver; ++ desc = &vc5_mock; ++ break; ++ ++ default: ++ return NULL; ++ } ++ + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0977-drm-vc4-tests-Drop-drm-parameter-for-vc4_find_crtc_f.patch b/target/linux/bcm27xx/patches-6.1/950-0977-drm-vc4-tests-Drop-drm-parameter-for-vc4_find_crtc_f.patch new file mode 100644 index 0000000000..42c4be9b8b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0977-drm-vc4-tests-Drop-drm-parameter-for-vc4_find_crtc_f.patch @@ -0,0 +1,63 @@ +From 70e906d3c688491e181446afa27bea32ce241d6a Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 09:58:15 +0100 +Subject: [PATCH] drm/vc4: tests: Drop drm parameter for + vc4_find_crtc_for_encoder + +The DRM device pointer and the DRM encoder pointer are redundant, since +the latter is attached to the former and we can just follow the +drm_encoder->dev pointer. + +Let's remove the drm_device pointer argument. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 2 +- + drivers/gpu/drm/vc4/tests/vc4_mock_output.c | 4 ++-- + drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -7,9 +7,9 @@ + + static inline + struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit *test, +- struct drm_device *drm, + struct drm_encoder *encoder) + { ++ struct drm_device *drm = encoder->dev; + struct drm_crtc *crtc; + + KUNIT_ASSERT_EQ(test, hweight32(encoder->possible_crtcs), 1); +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c +@@ -77,7 +77,7 @@ int vc4_mock_atomic_add_output(struct ku + encoder = vc4_find_encoder_by_type(drm, type); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + +- crtc = vc4_find_crtc_for_encoder(test, drm, encoder); ++ crtc = vc4_find_crtc_for_encoder(test, encoder); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + + output = container_of(encoder, struct vc4_dummy_output, encoder.base); +@@ -115,7 +115,7 @@ int vc4_mock_atomic_del_output(struct ku + encoder = vc4_find_encoder_by_type(drm, type); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + +- crtc = vc4_find_crtc_for_encoder(test, drm, encoder); ++ crtc = vc4_find_crtc_for_encoder(test, encoder); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + + crtc_state = drm_atomic_get_crtc_state(state, crtc); +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -132,7 +132,7 @@ get_vc4_crtc_state_for_encoder(struct ku + encoder = vc4_find_encoder_by_type(drm, type); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + +- crtc = vc4_find_crtc_for_encoder(test, drm, encoder); ++ crtc = vc4_find_crtc_for_encoder(test, encoder); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); diff --git a/target/linux/bcm27xx/patches-6.1/950-0978-drm-vc4-tests-Return-the-allocated-output.patch b/target/linux/bcm27xx/patches-6.1/950-0978-drm-vc4-tests-Return-the-allocated-output.patch new file mode 100644 index 0000000000..6f49d52f32 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0978-drm-vc4-tests-Return-the-allocated-output.patch @@ -0,0 +1,174 @@ +From 14e97c5765579eaab3c8372701750ffa30e4c7da Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 10:02:59 +0100 +Subject: [PATCH] drm/vc4: tests: Return the allocated output + +Some tests will need to retrieve the output that was just allocated by +vc4_mock_atomic_add_output(). + +Instead of making them look them up in the DRM device, we can simply +make vc4_mock_atomic_add_output() return an error pointer that holds the +allocated output instead of the error code. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 7 ++-- + drivers/gpu/drm/vc4/tests/vc4_mock_output.c | 9 +++-- + .../gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 37 +++++++++++-------- + 3 files changed, 30 insertions(+), 23 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -53,9 +53,10 @@ struct vc4_dummy_output *vc4_dummy_outpu + struct vc4_dev *vc4_mock_device(struct kunit *test); + struct vc4_dev *vc5_mock_device(struct kunit *test); + +-int vc4_mock_atomic_add_output(struct kunit *test, +- struct drm_atomic_state *state, +- enum vc4_encoder_type type); ++struct vc4_dummy_output * ++vc4_mock_atomic_add_output(struct kunit *test, ++ struct drm_atomic_state *state, ++ enum vc4_encoder_type type); + int vc4_mock_atomic_del_output(struct kunit *test, + struct drm_atomic_state *state, + enum vc4_encoder_type type); +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c +@@ -61,9 +61,10 @@ static const struct drm_display_mode def + DRM_SIMPLE_MODE(640, 480, 64, 48) + }; + +-int vc4_mock_atomic_add_output(struct kunit *test, +- struct drm_atomic_state *state, +- enum vc4_encoder_type type) ++struct vc4_dummy_output * ++vc4_mock_atomic_add_output(struct kunit *test, ++ struct drm_atomic_state *state, ++ enum vc4_encoder_type type) + { + struct drm_device *drm = state->dev; + struct drm_connector_state *conn_state; +@@ -96,7 +97,7 @@ int vc4_mock_atomic_add_output(struct ku + + crtc_state->active = true; + +- return 0; ++ return output; + } + + int vc4_mock_atomic_del_output(struct kunit *test, +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -683,10 +683,11 @@ static void drm_vc4_test_pv_muxing(struc + int ret; + + for (i = 0; i < params->nencoders; i++) { ++ struct vc4_dummy_output *output; + enum vc4_encoder_type enc_type = params->encoders[i]; + +- ret = vc4_mock_atomic_add_output(test, state, enc_type); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, enc_type); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + } + + ret = drm_atomic_check_only(state); +@@ -712,10 +713,11 @@ static void drm_vc4_test_pv_muxing_inval + int ret; + + for (i = 0; i < params->nencoders; i++) { ++ struct vc4_dummy_output *output; + enum vc4_encoder_type enc_type = params->encoders[i]; + +- ret = vc4_mock_atomic_add_output(test, state, enc_type); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, enc_type); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + } + + ret = drm_atomic_check_only(state); +@@ -804,6 +806,7 @@ static void drm_test_vc5_pv_muxing_bugs_ + { + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; ++ struct vc4_dummy_output *output; + struct vc4_crtc_state *new_vc4_crtc_state; + struct vc4_hvs_state *new_hvs_state; + unsigned int hdmi0_channel; +@@ -823,8 +826,8 @@ static void drm_test_vc5_pv_muxing_bugs_ + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -850,8 +853,8 @@ static void drm_test_vc5_pv_muxing_bugs_ + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -880,6 +883,7 @@ static void drm_test_vc5_pv_muxing_bugs_ + { + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; ++ struct vc4_dummy_output *output; + struct vc4_crtc_state *new_vc4_crtc_state; + struct vc4_hvs_state *new_hvs_state; + unsigned int old_hdmi0_channel; +@@ -899,11 +903,11 @@ static void drm_test_vc5_pv_muxing_bugs_ + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -971,6 +975,7 @@ drm_test_vc5_pv_muxing_bugs_subsequent_c + { + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; ++ struct vc4_dummy_output *output; + struct vc4_crtc_state *new_vc4_crtc_state; + struct drm_device *drm; + struct vc4_dev *vc4; +@@ -987,8 +992,8 @@ drm_test_vc5_pv_muxing_bugs_subsequent_c + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -1003,8 +1008,8 @@ drm_test_vc5_pv_muxing_bugs_subsequent_c + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); diff --git a/target/linux/bcm27xx/patches-6.1/950-0979-drm-vc4-tests-Add-BCM2712-mock-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0979-drm-vc4-tests-Add-BCM2712-mock-driver.patch new file mode 100644 index 0000000000..8c12375284 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0979-drm-vc4-tests-Add-BCM2712-mock-driver.patch @@ -0,0 +1,87 @@ +From 04bec005b049604f862765b35ebd71c2a69b9e7c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:38:10 +0100 +Subject: [PATCH] drm/vc4: tests: Add BCM2712 mock driver + +The BCM2712 has a simpler pipeline that can only output to a writeback +connector and two HDMI controllers. + +Let's allow our kunit tests to create a mock of that pipeline. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 29 ++++++++++++++++++++++++++++ + drivers/gpu/drm/vc4/tests/vc4_mock.h | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ + 3 files changed, 32 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -106,6 +106,26 @@ static const struct vc4_mock_desc vc5_mo + DRM_MODE_CONNECTOR_HDMIA)), + ); + ++static const struct vc4_mock_desc vc6_mock = ++ VC4_MOCK_DESC( ++ VC4_MOCK_CRTC_DESC(&bcm2712_mop_data.base, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP0, ++ DRM_MODE_ENCODER_VIRTUAL, ++ DRM_MODE_CONNECTOR_WRITEBACK)), ++ VC4_MOCK_CRTC_DESC(&bcm2712_moplet_data.base, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP1, ++ DRM_MODE_ENCODER_VIRTUAL, ++ DRM_MODE_CONNECTOR_WRITEBACK)), ++ VC4_MOCK_PIXELVALVE_DESC(&bcm2712_pv0_data, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0, ++ DRM_MODE_ENCODER_TMDS, ++ DRM_MODE_CONNECTOR_HDMIA)), ++ VC4_MOCK_PIXELVALVE_DESC(&bcm2712_pv1_data, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI1, ++ DRM_MODE_ENCODER_TMDS, ++ DRM_MODE_CONNECTOR_HDMIA)), ++); ++ + static int __build_one_pipe(struct kunit *test, struct drm_device *drm, + const struct vc4_mock_pipe_desc *pipe) + { +@@ -171,6 +191,10 @@ static struct vc4_dev *__mock_device(str + drv = &vc5_drm_driver; + desc = &vc5_mock; + break; ++ case VC4_GEN_6: ++ drv = &vc5_drm_driver; ++ desc = &vc6_mock; ++ break; + + default: + return NULL; +@@ -212,3 +236,8 @@ struct vc4_dev *vc5_mock_device(struct k + { + return __mock_device(test, VC4_GEN_5); + } ++ ++struct vc4_dev *vc6_mock_device(struct kunit *test) ++{ ++ return __mock_device(test, VC4_GEN_6); ++} +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -52,6 +52,7 @@ struct vc4_dummy_output *vc4_dummy_outpu + + struct vc4_dev *vc4_mock_device(struct kunit *test); + struct vc4_dev *vc5_mock_device(struct kunit *test); ++struct vc4_dev *vc6_mock_device(struct kunit *test); + + struct vc4_dummy_output * + vc4_mock_atomic_add_output(struct kunit *test, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -570,6 +570,8 @@ struct vc4_txp_data { + unsigned int supports_40bit_addresses:1; + }; + ++extern const struct vc4_txp_data bcm2712_mop_data; ++extern const struct vc4_txp_data bcm2712_moplet_data; + extern const struct vc4_txp_data bcm2835_txp_data; + + struct vc4_pv_data { diff --git a/target/linux/bcm27xx/patches-6.1/950-0980-drm-vc4-tests-Add-tests-for-BCM2712-PixelValve-Muxin.patch b/target/linux/bcm27xx/patches-6.1/950-0980-drm-vc4-tests-Add-tests-for-BCM2712-PixelValve-Muxin.patch new file mode 100644 index 0000000000..6c0db592c9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0980-drm-vc4-tests-Add-tests-for-BCM2712-PixelValve-Muxin.patch @@ -0,0 +1,138 @@ +From 77c14764ae164b7969e65437a87aca25b30d8b80 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:14:22 +0200 +Subject: [PATCH] drm/vc4: tests: Add tests for BCM2712 PixelValve Muxing + +The BCM2712 has a simpler pipeline than the BCM2711, and thus the muxing +requirements are different. Create some tests to make sure we get proper +muxing decisions. + +Signed-off-by: Maxime Ripard +--- + .../gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 81 +++++++++++++++++++ + 1 file changed, 81 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -105,6 +105,13 @@ static const struct encoder_constraint v + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2), + }; + ++static const struct encoder_constraint vc6_encoder_constraints[] = { ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 1), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP1, 1), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 2), ++}; ++ + static bool check_vc4_encoder_constraints(enum vc4_encoder_type type, unsigned int channel) + { + return __check_encoder_constraints(vc4_encoder_constraints, +@@ -119,6 +126,13 @@ static bool check_vc5_encoder_constraint + type, channel); + } + ++static bool check_vc6_encoder_constraints(enum vc4_encoder_type type, unsigned int channel) ++{ ++ return __check_encoder_constraints(vc6_encoder_constraints, ++ ARRAY_SIZE(vc6_encoder_constraints), ++ type, channel); ++} ++ + static struct vc4_crtc_state * + get_vc4_crtc_state_for_encoder(struct kunit *test, + const struct drm_atomic_state *state, +@@ -196,6 +210,9 @@ static void vc4_test_pv_muxing_desc(cons + #define VC5_PV_MUXING_TEST(_name, ...) \ + PV_MUXING_TEST(_name, vc5_mock_device, check_vc5_encoder_constraints, __VA_ARGS__) + ++#define VC6_PV_MUXING_TEST(_name, ...) \ ++ PV_MUXING_TEST(_name, vc6_mock_device, check_vc6_encoder_constraints, __VA_ARGS__) ++ + static const struct pv_muxing_param vc4_test_pv_muxing_params[] = { + VC4_PV_MUXING_TEST("1 output: DSI0", + VC4_ENCODER_TYPE_DSI0), +@@ -674,6 +691,54 @@ KUNIT_ARRAY_PARAM(vc5_test_pv_muxing_inv + vc5_test_pv_muxing_invalid_params, + vc4_test_pv_muxing_desc); + ++static const struct pv_muxing_param vc6_test_pv_muxing_params[] = { ++ VC6_PV_MUXING_TEST("1 output: HDMI0", ++ VC4_ENCODER_TYPE_HDMI0), ++ VC6_PV_MUXING_TEST("1 output: HDMI1", ++ VC4_ENCODER_TYPE_HDMI1), ++ VC6_PV_MUXING_TEST("1 output: MOPLET", ++ VC4_ENCODER_TYPE_TXP1), ++ VC6_PV_MUXING_TEST("1 output: MOP", ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_HDMI1), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI0, MOPLET", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_TXP1), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI0, MOP", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI1, MOP", ++ VC4_ENCODER_TYPE_HDMI1, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("2 outputs: MOPLET, MOP", ++ VC4_ENCODER_TYPE_TXP1, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("3 outputs: HDMI0, HDMI1, MOP", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_HDMI1, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("3 outputs: HDMI0, MOPLET, MOP", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_TXP1, ++ VC4_ENCODER_TYPE_TXP0), ++}; ++ ++KUNIT_ARRAY_PARAM(vc6_test_pv_muxing, ++ vc6_test_pv_muxing_params, ++ vc4_test_pv_muxing_desc); ++ ++static const struct pv_muxing_param vc6_test_pv_muxing_invalid_params[] = { ++ VC6_PV_MUXING_TEST("HDMI1/MOPLET Conflict", ++ VC4_ENCODER_TYPE_HDMI1, ++ VC4_ENCODER_TYPE_TXP1), ++}; ++ ++KUNIT_ARRAY_PARAM(vc6_test_pv_muxing_invalid, ++ vc6_test_pv_muxing_invalid_params, ++ vc4_test_pv_muxing_desc); ++ + static void drm_vc4_test_pv_muxing(struct kunit *test) + { + const struct pv_muxing_param *params = test->param_value; +@@ -797,6 +862,21 @@ static struct kunit_suite vc5_pv_muxing_ + .test_cases = vc5_pv_muxing_tests, + }; + ++static struct kunit_case vc6_pv_muxing_tests[] = { ++ KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing, ++ vc6_test_pv_muxing_gen_params), ++ KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid, ++ vc6_test_pv_muxing_invalid_gen_params), ++ {} ++}; ++ ++static struct kunit_suite vc6_pv_muxing_test_suite = { ++ .name = "vc6-pv-muxing-combinations", ++ .init = vc4_pv_muxing_test_init, ++ .exit = vc4_pv_muxing_test_exit, ++ .test_cases = vc6_pv_muxing_tests, ++}; ++ + /* See + * https://lore.kernel.org/all/3e113525-aa89-b1e2-56b7-ca55bd41d057@samsung.com/ + * and +@@ -1040,5 +1120,6 @@ static struct kunit_suite vc5_pv_muxing_ + kunit_test_suites( + &vc4_pv_muxing_test_suite, + &vc5_pv_muxing_test_suite, ++ &vc6_pv_muxing_test_suite, + &vc5_pv_muxing_bugs_test_suite + ); diff --git a/target/linux/bcm27xx/patches-6.1/950-0981-drm-vc4-fkms-Rename-plane-related-functions.patch b/target/linux/bcm27xx/patches-6.1/950-0981-drm-vc4-fkms-Rename-plane-related-functions.patch new file mode 100644 index 0000000000..455c64ad2e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0981-drm-vc4-fkms-Rename-plane-related-functions.patch @@ -0,0 +1,64 @@ +From 3d849ab48cecab55862a4f2742f11937d66ba54b Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:21:34 +0200 +Subject: [PATCH] drm/vc4: fkms: Rename plane related functions + +The name collide with the Full KMS functions that are going to be made +public. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -670,8 +670,8 @@ static int vc4_plane_to_mb(struct drm_pl + return 0; + } + +-static int vc4_plane_atomic_check(struct drm_plane *plane, +- struct drm_atomic_state *state) ++static int vc4_fkms_plane_atomic_check(struct drm_plane *plane, ++ struct drm_atomic_state *state) + { + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); +@@ -728,7 +728,7 @@ static int vc4_plane_atomic_async_check( + } + + /* Called during init to allocate the plane's atomic state. */ +-static void vc4_plane_reset(struct drm_plane *plane) ++static void vc4_fkms_plane_reset(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + +@@ -788,7 +788,7 @@ static bool vc4_fkms_format_mod_supporte + } + } + +-static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) ++static struct drm_plane_state *vc4_fkms_plane_duplicate_state(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + +@@ -809,8 +809,8 @@ static const struct drm_plane_funcs vc4_ + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = vc4_plane_destroy, + .set_property = NULL, +- .reset = vc4_plane_reset, +- .atomic_duplicate_state = vc4_plane_duplicate_state, ++ .reset = vc4_fkms_plane_reset, ++ .atomic_duplicate_state = vc4_fkms_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + .format_mod_supported = vc4_fkms_format_mod_supported, + }; +@@ -818,7 +818,7 @@ static const struct drm_plane_funcs vc4_ + static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .cleanup_fb = NULL, +- .atomic_check = vc4_plane_atomic_check, ++ .atomic_check = vc4_fkms_plane_atomic_check, + .atomic_update = vc4_plane_atomic_update, + .atomic_disable = vc4_plane_atomic_disable, + .atomic_async_check = vc4_plane_atomic_async_check, diff --git a/target/linux/bcm27xx/patches-6.1/950-0982-drm-vc4-tests-Use-custom-plane-state-for-mock.patch b/target/linux/bcm27xx/patches-6.1/950-0982-drm-vc4-tests-Use-custom-plane-state-for-mock.patch new file mode 100644 index 0000000000..0105753a91 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0982-drm-vc4-tests-Use-custom-plane-state-for-mock.patch @@ -0,0 +1,95 @@ +From 14fe42ff341741d60ba338c401855dee7fb68754 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:24:37 +0200 +Subject: [PATCH] drm/vc4: tests: Use custom plane state for mock + +The current mock planes were just using the regular drm_plane_state, +while the driver expect struct vc4_plane_state that subclasses +drm_plane_state. + +Hook the proper implementations of reset, duplicate_state, destroy and +atomic_check to create vc4_plane_state. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 7 ++++--- + drivers/gpu/drm/vc4/vc4_drv.h | 6 ++++++ + drivers/gpu/drm/vc4/vc4_plane.c | 12 ++++++------ + 3 files changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c +@@ -10,12 +10,13 @@ + #include "vc4_mock.h" + + static const struct drm_plane_helper_funcs vc4_dummy_plane_helper_funcs = { ++ .atomic_check = vc4_plane_atomic_check, + }; + + static const struct drm_plane_funcs vc4_dummy_plane_funcs = { +- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, +- .reset = drm_atomic_helper_plane_reset, ++ .atomic_destroy_state = vc4_plane_destroy_state, ++ .atomic_duplicate_state = vc4_plane_duplicate_state, ++ .reset = vc4_plane_reset, + }; + + static const uint32_t vc4_dummy_plane_formats[] = { +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -1145,6 +1145,12 @@ int vc4_kms_load(struct drm_device *dev) + struct drm_plane *vc4_plane_init(struct drm_device *dev, + enum drm_plane_type type, + uint32_t possible_crtcs); ++void vc4_plane_reset(struct drm_plane *plane); ++void vc4_plane_destroy_state(struct drm_plane *plane, ++ struct drm_plane_state *state); ++struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane); ++int vc4_plane_atomic_check(struct drm_plane *plane, ++ struct drm_atomic_state *state); + int vc4_plane_create_additional_planes(struct drm_device *dev); + u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); + u32 vc4_plane_dlist_size(const struct drm_plane_state *state); +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -276,7 +276,7 @@ static bool plane_enabled(struct drm_pla + return state->fb && !WARN_ON(!state->crtc); + } + +-static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) ++struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + unsigned int i; +@@ -312,8 +312,8 @@ static struct drm_plane_state *vc4_plane + return &vc4_state->base; + } + +-static void vc4_plane_destroy_state(struct drm_plane *plane, +- struct drm_plane_state *state) ++void vc4_plane_destroy_state(struct drm_plane *plane, ++ struct drm_plane_state *state) + { + struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct vc4_hvs *hvs = vc4->hvs; +@@ -348,7 +348,7 @@ static void vc4_plane_destroy_state(stru + } + + /* Called during init to allocate the plane's atomic state. */ +-static void vc4_plane_reset(struct drm_plane *plane) ++void vc4_plane_reset(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + +@@ -2000,8 +2000,8 @@ static int vc6_plane_mode_set(struct drm + * compute the dlist here and have all active plane dlists get updated + * in the CRTC's flush. + */ +-static int vc4_plane_atomic_check(struct drm_plane *plane, +- struct drm_atomic_state *state) ++int vc4_plane_atomic_check(struct drm_plane *plane, ++ struct drm_atomic_state *state) + { + struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, diff --git a/target/linux/bcm27xx/patches-6.1/950-0983-drm-vc4-tests-Add-function-to-lookup-a-plane-for-a-C.patch b/target/linux/bcm27xx/patches-6.1/950-0983-drm-vc4-tests-Add-function-to-lookup-a-plane-for-a-C.patch new file mode 100644 index 0000000000..ebab218cf3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0983-drm-vc4-tests-Add-function-to-lookup-a-plane-for-a-C.patch @@ -0,0 +1,36 @@ +From 3320e449e40eeb49b601dcbbd4bd72b8cb8f3054 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:26:58 +0200 +Subject: [PATCH] drm/vc4: tests: Add function to lookup a plane for a CRTC + +Some tests will need to find a plane to run a test on for a given CRTC. +Let's create a small helper to do that. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -21,6 +21,20 @@ struct drm_crtc *vc4_find_crtc_for_encod + return NULL; + } + ++static inline ++struct drm_plane *vc4_mock_find_plane_for_crtc(struct kunit *test, ++ struct drm_crtc *crtc) ++{ ++ struct drm_device *drm = crtc->dev; ++ struct drm_plane *plane; ++ ++ drm_for_each_plane(plane, drm) ++ if (plane->possible_crtcs & drm_crtc_mask(crtc)) ++ return plane; ++ ++ return NULL; ++} ++ + struct vc4_dummy_plane { + struct vc4_plane plane; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0984-drm-vc4-tests-Add-helper-to-add-a-new-plane-to-a-sta.patch b/target/linux/bcm27xx/patches-6.1/950-0984-drm-vc4-tests-Add-helper-to-add-a-new-plane-to-a-sta.patch new file mode 100644 index 0000000000..7d230294fc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0984-drm-vc4-tests-Add-helper-to-add-a-new-plane-to-a-sta.patch @@ -0,0 +1,62 @@ +From a2f912c44b98acb6c10c977db105e199011c09b5 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 12:57:53 +0200 +Subject: [PATCH] drm/vc4: tests: Add helper to add a new plane to a state + +We'll start to add some tests for the plane state logic, so let's create +a helper to add a plane to an existing atomic state. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 4 ++++ + drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 22 ++++++++++++++++++++++ + 2 files changed, 26 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -42,6 +42,10 @@ struct vc4_dummy_plane { + struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test, + struct drm_device *drm, + enum drm_plane_type type); ++struct drm_plane * ++vc4_mock_atomic_add_plane(struct kunit *test, ++ struct drm_atomic_state *state, ++ struct drm_crtc *crtc); + + struct vc4_dummy_crtc { + struct vc4_crtc crtc; +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 + + #include ++#include + #include + #include + #include +@@ -46,3 +47,24 @@ struct vc4_dummy_plane *vc4_dummy_plane( + + return dummy_plane; + } ++ ++struct drm_plane * ++vc4_mock_atomic_add_plane(struct kunit *test, ++ struct drm_atomic_state *state, ++ struct drm_crtc *crtc) ++{ ++ struct drm_plane_state *plane_state; ++ struct drm_plane *plane; ++ int ret; ++ ++ plane = vc4_mock_find_plane_for_crtc(test, crtc); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); ++ ++ plane_state = drm_atomic_get_plane_state(state, plane); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_state); ++ ++ ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); ++ KUNIT_EXPECT_EQ(test, ret, 0); ++ ++ return plane; ++} diff --git a/target/linux/bcm27xx/patches-6.1/950-0985-drm-vc4-tests-Support-a-few-more-plane-formats.patch b/target/linux/bcm27xx/patches-6.1/950-0985-drm-vc4-tests-Support-a-few-more-plane-formats.patch new file mode 100644 index 0000000000..191181dbb6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0985-drm-vc4-tests-Support-a-few-more-plane-formats.patch @@ -0,0 +1,26 @@ +From 418d2e0e652c3870c29dd2e462f052a88fa027da Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 12:59:05 +0200 +Subject: [PATCH] drm/vc4: tests: Support a few more plane formats + +We'll start testing our planes code in situations where we will use more +than XRGB8888, so let's add a few common pixel formats. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c +@@ -21,7 +21,10 @@ static const struct drm_plane_funcs vc4_ + }; + + static const uint32_t vc4_dummy_plane_formats[] = { ++ DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_YUV420, ++ DRM_FORMAT_YUV422, + }; + + struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test, diff --git a/target/linux/bcm27xx/patches-6.1/950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch b/target/linux/bcm27xx/patches-6.1/950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch new file mode 100644 index 0000000000..5902d141ef --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch @@ -0,0 +1,358 @@ +From 39ae36d19bf6e59e3091f8f0ec6f4eac59aaf6f2 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 13:43:32 +0200 +Subject: [PATCH] drm/vc4: tests: Introduce a test for LBM buffer size + +The BCM2712 comes with a different LBM size computation than the +previous generations, so let's add the few examples provided as kunit +tests to make sure we always satisfy those requirements. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/Makefile | 3 +- + drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c | 327 ++++++++++++++++++ + 2 files changed, 329 insertions(+), 1 deletion(-) + create mode 100644 drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c + +--- a/drivers/gpu/drm/vc4/Makefile ++++ b/drivers/gpu/drm/vc4/Makefile +@@ -31,7 +31,8 @@ vc4-$(CONFIG_DRM_VC4_KUNIT_TEST) += \ + tests/vc4_mock_crtc.o \ + tests/vc4_mock_output.o \ + tests/vc4_mock_plane.o \ +- tests/vc4_test_pv_muxing.o ++ tests/vc4_test_pv_muxing.o \ ++ tests/vc4_test_lbm_size.o + + vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o + +--- /dev/null ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c +@@ -0,0 +1,327 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../drm_crtc_internal.h" ++#include "../../drm_internal.h" ++ ++#include ++ ++#include "../vc4_drv.h" ++ ++#include "vc4_mock.h" ++ ++u32 vc4_lbm_size(struct drm_plane_state *state); ++ ++struct vc4_lbm_size_priv { ++ struct vc4_dev *vc4; ++ struct drm_file *file; ++ struct drm_modeset_acquire_ctx ctx; ++ struct drm_atomic_state *state; ++}; ++ ++struct vc4_lbm_size_param { ++ unsigned int src_w, src_h; ++ unsigned int crtc_w, crtc_h; ++ bool forced_alpha; ++ u32 fourcc; ++ enum vc4_scaling_mode expected_x_scaling[2]; ++ enum vc4_scaling_mode expected_y_scaling[2]; ++ unsigned int expected_lbm_size; ++}; ++ ++static const struct vc4_lbm_size_param vc4_test_lbm_size_params[] = { ++ { ++ .src_w = 256, ++ .crtc_w = 256, ++ .src_h = 256, ++ .crtc_h = 512, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 32, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 179, ++ .src_h = 256, ++ .crtc_h = 512, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 23, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 256, ++ .src_h = 256, ++ .crtc_h = 512, ++ .fourcc = DRM_FORMAT_XRGB8888, ++ .expected_x_scaling = { VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 24, ++ }, ++ { ++ .src_w = 100, ++ .crtc_w = 73, ++ .src_h = 100, ++ .crtc_h = 73, ++ .fourcc = DRM_FORMAT_XRGB8888, ++ .expected_x_scaling = { VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 8, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 256, ++ .src_h = 256, ++ .crtc_h = 512, ++ .forced_alpha = true, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 24, ++ }, ++ { ++ .src_w = 100, ++ .crtc_w = 73, ++ .src_h = 100, ++ .crtc_h = 73, ++ .forced_alpha = true, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 8, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 94, ++ .src_h = 256, ++ .crtc_h = 94, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_TPZ, }, ++ .expected_y_scaling = { VC4_SCALING_TPZ, }, ++ .expected_lbm_size = 6, ++ }, ++ ++/* ++ * TODO: Those tests reflect the LBM size calculation examples, but the ++ * driver ends up taking different scaler filters decisions, and thus ++ * doesn't end up with the same sizes. It would be valuable to have ++ * those tests, but the driver doesn't take a bad decision either, so ++ * it's not clear what we should do at this point. ++ */ ++#if 0 ++ { ++ .src_w = 320, ++ .crtc_w = 320, ++ .src_h = 320, ++ .crtc_h = 320, ++ .fourcc = DRM_FORMAT_YUV420, ++ .expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_NONE, VC4_SCALING_PPF, }, ++ .expected_lbm_size = 10, ++ }, ++ { ++ .src_w = 512, ++ .crtc_w = 512, ++ .src_h = 512, ++ .crtc_h = 256, ++ .fourcc = DRM_FORMAT_YUV420, ++ .expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_NONE, }, ++ .expected_lbm_size = 5, ++ }, ++ { ++ .src_w = 486, ++ .crtc_w = 157, ++ .src_h = 404, ++ .crtc_h = 929, ++ .fourcc = DRM_FORMAT_YUV422, ++ .expected_x_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, }, ++ .expected_lbm_size = 20, ++ }, ++ { ++ .src_w = 320, ++ .crtc_w = 128, ++ .src_h = 176, ++ .crtc_h = 70, ++ .fourcc = DRM_FORMAT_YUV420, ++ .expected_x_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, }, ++ .expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, }, ++ .expected_lbm_size = 8, ++ }, ++#endif ++}; ++ ++static void vc4_test_lbm_size_desc(const struct vc4_lbm_size_param *t, char *desc) ++{ ++ snprintf(desc, KUNIT_PARAM_DESC_SIZE, ++ "%ux%u to %ux%u %s(%p4cc)", ++ t->src_w, t->src_h, ++ t->crtc_w, t->crtc_h, ++ t->forced_alpha ? "with forced alpha " : "", ++ &t->fourcc); ++} ++ ++KUNIT_ARRAY_PARAM(vc4_test_lbm_size, ++ vc4_test_lbm_size_params, ++ vc4_test_lbm_size_desc); ++ ++static void drm_vc4_test_vc4_lbm_size(struct kunit *test) ++{ ++ const struct vc4_lbm_size_param *params = test->param_value; ++ const struct vc4_lbm_size_priv *priv = test->priv; ++ const struct drm_format_info *info; ++ struct drm_mode_fb_cmd2 fb_req = { }; ++ struct drm_atomic_state *state = priv->state; ++ struct vc4_plane_state *vc4_plane_state; ++ struct drm_plane_state *plane_state; ++ struct vc4_dummy_output *output; ++ struct drm_framebuffer *fb; ++ struct drm_plane *plane; ++ struct drm_crtc *crtc; ++ unsigned int i; ++ int ret; ++ ++ info = drm_format_info(params->fourcc); ++ KUNIT_ASSERT_NOT_NULL(test, info); ++ ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); ++ ++ crtc = vc4_find_crtc_for_encoder(test, &output->encoder.base); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); ++ ++ plane = vc4_mock_atomic_add_plane(test, state, crtc); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); ++ ++ plane_state = drm_atomic_get_plane_state(state, plane); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_state); ++ ++ vc4_plane_state = to_vc4_plane_state(plane_state); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4_plane_state); ++ ++ fb_req.pixel_format = params->fourcc; ++ fb_req.width = params->src_w; ++ fb_req.height = params->src_h; ++ ++ for (i = 0; i < info->num_planes; i++) { ++ struct drm_mode_create_dumb dumb_args = { }; ++ ++ dumb_args.width = params->src_w; ++ dumb_args.height = params->src_h; ++ dumb_args.bpp = drm_format_info_bpp(info, i); ++ ++ ret = drm_mode_create_dumb(state->dev, &dumb_args, priv->file); ++ KUNIT_ASSERT_EQ(test, ret, 0); ++ ++ fb_req.handles[i] = dumb_args.handle; ++ fb_req.pitches[i] = dumb_args.pitch; ++ } ++ ++ fb = drm_internal_framebuffer_create(state->dev, &fb_req, priv->file); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb); ++ ++ drm_atomic_set_fb_for_plane(plane_state, fb); ++ ++ plane_state->src_x = 0; ++ plane_state->src_y = 0; ++ plane_state->src_h = params->src_h << 16; ++ plane_state->src_w = params->src_w << 16; ++ ++ plane_state->crtc_x = 0; ++ plane_state->crtc_y = 0; ++ plane_state->crtc_h = params->crtc_h; ++ plane_state->crtc_w = params->crtc_w; ++ ++ if (params->forced_alpha) ++ plane_state->alpha = 128; ++ ++ ret = drm_atomic_check_only(state); ++ KUNIT_ASSERT_EQ(test, ret, 0); ++ ++ KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm.size, params->expected_lbm_size); ++ ++ for (i = 0; i < 2; i++) { ++ KUNIT_EXPECT_EQ(test, ++ vc4_plane_state->x_scaling[i], ++ params->expected_x_scaling[i]); ++ KUNIT_EXPECT_EQ(test, ++ vc4_plane_state->y_scaling[i], ++ params->expected_y_scaling[i]); ++ } ++ ++ drm_framebuffer_put(fb); ++ ++ for (i = 0; i < info->num_planes; i++) ++ drm_mode_destroy_dumb(state->dev, fb_req.handles[i], priv->file); ++} ++ ++static struct kunit_case vc4_lbm_size_tests[] = { ++ KUNIT_CASE_PARAM(drm_vc4_test_vc4_lbm_size, ++ vc4_test_lbm_size_gen_params), ++ {} ++}; ++ ++static int vc4_lbm_size_test_init(struct kunit *test) ++{ ++ struct drm_atomic_state *state; ++ struct vc4_lbm_size_priv *priv; ++ struct drm_device *drm; ++ struct vc4_dev *vc4; ++ ++ priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_NULL(test, priv); ++ test->priv = priv; ++ ++ vc4 = vc6_mock_device(test); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); ++ priv->vc4 = vc4; ++ ++ priv->file = drm_file_alloc(priv->vc4->base.primary); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->file); ++ ++ drm_modeset_acquire_init(&priv->ctx, 0); ++ ++ drm = &vc4->base; ++ state = drm_atomic_state_alloc(drm); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ++ ++ state->acquire_ctx = &priv->ctx; ++ ++ priv->state = state; ++ ++ return 0; ++} ++ ++static void vc4_lbm_size_test_exit(struct kunit *test) ++{ ++ struct vc4_lbm_size_priv *priv = test->priv; ++ struct vc4_dev *vc4 = priv->vc4; ++ struct drm_device *drm = &vc4->base; ++ struct drm_atomic_state *state = priv->state; ++ ++ drm_atomic_state_put(state); ++ drm_modeset_drop_locks(&priv->ctx); ++ drm_modeset_acquire_fini(&priv->ctx); ++ drm_file_free(priv->file); ++ drm_dev_unregister(drm); ++ drm_kunit_helper_free_device(test, vc4->dev); ++} ++ ++static struct kunit_suite vc4_lbm_size_test_suite = { ++ .name = "vc4-lbm-size", ++ .init = vc4_lbm_size_test_init, ++ .exit = vc4_lbm_size_test_exit, ++ .test_cases = vc4_lbm_size_tests, ++}; ++ ++kunit_test_suite(vc4_lbm_size_test_suite); diff --git a/target/linux/bcm27xx/patches-6.1/950-0987-drm-vc4-kms-Avoid-setting-core-and-disp-clocks-for-h.patch b/target/linux/bcm27xx/patches-6.1/950-0987-drm-vc4-kms-Avoid-setting-core-and-disp-clocks-for-h.patch new file mode 100644 index 0000000000..f20b0cf3f8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0987-drm-vc4-kms-Avoid-setting-core-and-disp-clocks-for-h.patch @@ -0,0 +1,40 @@ +From 352d96c9e50012f2b5e5dde9933af8d570e7dc81 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Mon, 17 Jul 2023 17:45:32 +0100 +Subject: [PATCH] drm/vc4: kms: Avoid setting core and disp clocks for hdmi + modes + +On 2712, the firmware always runs these clock at a speed sufficient +for dual 4kp60. + +The requests here prevent the gpu from going into its lowest voltage +mode, so just skip the clock requests. + +With this applied the idle voltage on my pi 5 reduces from 0.7424V +to 0.72V. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_kms.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -435,7 +435,7 @@ static void vc4_atomic_commit_tail(struc + old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + +- if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long state_rate = max(old_hvs_state->core_clock_rate, + new_hvs_state->core_clock_rate); + unsigned long core_rate = clamp_t(unsigned long, state_rate, +@@ -489,7 +489,7 @@ static void vc4_atomic_commit_tail(struc + + drm_atomic_helper_cleanup_planes(dev, state); + +- if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long core_rate = min_t(unsigned long, + hvs->max_core_rate, + new_hvs_state->core_clock_rate); diff --git a/target/linux/bcm27xx/patches-6.1/950-0988-drm-vc4-Assign-LBM-memory-during-atomic_flush.patch b/target/linux/bcm27xx/patches-6.1/950-0988-drm-vc4-Assign-LBM-memory-during-atomic_flush.patch new file mode 100644 index 0000000000..b489bbc7f7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0988-drm-vc4-Assign-LBM-memory-during-atomic_flush.patch @@ -0,0 +1,240 @@ +From bb0839405b61da6e6ae7141f7433f6a121725e6f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 31 Aug 2023 11:45:38 +0100 +Subject: [PATCH] drm/vc4: Assign LBM memory during atomic_flush. + +Avoid double buffering LBM allocations by making the +allocation a single alloc per crtc at atomic_flush. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c | 2 +- + drivers/gpu/drm/vc4/vc4_drv.h | 8 ++-- + drivers/gpu/drm/vc4/vc4_hvs.c | 47 ++++++++++++++++++- + drivers/gpu/drm/vc4/vc4_plane.c | 38 +++------------ + 4 files changed, 58 insertions(+), 37 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c +@@ -248,7 +248,7 @@ static void drm_vc4_test_vc4_lbm_size(st + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + +- KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm.size, params->expected_lbm_size); ++ KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm_size, params->expected_lbm_size); + + for (i = 0; i < 2; i++) { + KUNIT_EXPECT_EQ(test, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -437,6 +437,8 @@ struct vc4_plane_state { + u32 dlist_size; /* Number of dwords allocated for the display list */ + u32 dlist_count; /* Number of used dwords in the display list. */ + ++ u32 lbm_size; /* LBM requirements for this plane */ ++ + /* Offset in the dlist to various words, for pageflip or + * cursor updates. + */ +@@ -462,9 +464,6 @@ struct vc4_plane_state { + bool is_unity; + bool is_yuv; + +- /* Our allocation in LBM for temporary storage during scaling. */ +- struct drm_mm_node lbm; +- + /* Our allocation in UPM for prefetching. */ + struct drm_mm_node upm[DRM_FORMAT_MAX_PLANES]; + +@@ -661,6 +660,9 @@ struct vc4_crtc { + * access to that value. + */ + unsigned int current_hvs_channel; ++ ++ /* @lbm: Our allocation in LBM for temporary storage during scaling. */ ++ struct drm_mm_node lbm; + }; + + static inline struct vc4_crtc * +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1103,6 +1103,7 @@ int vc4_hvs_atomic_check(struct drm_crtc + struct drm_plane *plane; + const struct drm_plane_state *plane_state; + u32 dlist_count = 0; ++ u32 lbm_count = 0; + + /* The pixelvalve can only feed one encoder (and encoders are + * 1:1 with connectors.) +@@ -1111,6 +1112,8 @@ int vc4_hvs_atomic_check(struct drm_crtc + return -EINVAL; + + drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { ++ const struct vc4_plane_state *vc4_plane_state = ++ to_vc4_plane_state(plane_state); + u32 plane_dlist_count = vc4_plane_dlist_size(plane_state); + + drm_dbg_driver(dev, "[CRTC:%d:%s] Found [PLANE:%d:%s] with DLIST size: %u\n", +@@ -1119,6 +1122,7 @@ int vc4_hvs_atomic_check(struct drm_crtc + plane_dlist_count); + + dlist_count += plane_dlist_count; ++ lbm_count += vc4_plane_state->lbm_size; + } + + dlist_count++; /* Account for SCALER_CTL0_END. */ +@@ -1132,6 +1136,8 @@ int vc4_hvs_atomic_check(struct drm_crtc + + vc4_state->mm = alloc; + ++ /* FIXME: Check total lbm allocation here */ ++ + return vc4_hvs_gamma_check(crtc, state); + } + +@@ -1246,7 +1252,10 @@ void vc4_hvs_atomic_flush(struct drm_crt + bool debug_dump_regs = false; + bool enable_bg_fill = false; + u32 __iomem *dlist_start, *dlist_next; ++ unsigned long irqflags; + unsigned int zpos = 0; ++ u32 lbm_offset = 0; ++ u32 lbm_size = 0; + bool found = false; + int idx; + +@@ -1265,6 +1274,35 @@ void vc4_hvs_atomic_flush(struct drm_crt + vc4_hvs_dump_state(hvs); + } + ++ drm_atomic_crtc_for_each_plane(plane, crtc) { ++ vc4_plane_state = to_vc4_plane_state(plane->state); ++ lbm_size += vc4_plane_state->lbm_size; ++ } ++ ++ if (drm_mm_node_allocated(&vc4_crtc->lbm)) { ++ spin_lock_irqsave(&vc4_crtc->irq_lock, irqflags); ++ drm_mm_remove_node(&vc4_crtc->lbm); ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, irqflags); ++ } ++ ++ if (lbm_size) { ++ int ret; ++ ++ spin_lock_irqsave(&vc4_crtc->irq_lock, irqflags); ++ ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, ++ &vc4_crtc->lbm, ++ lbm_size, 1, ++ 0, 0); ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, irqflags); ++ ++ if (ret) { ++ pr_err("Failed to allocate LBM ret %d\n", ret); ++ return; ++ } ++ } ++ ++ lbm_offset = vc4_crtc->lbm.start; ++ + dlist_start = vc4->hvs->dlist + vc4_state->mm->mm_node.start; + dlist_next = dlist_start; + +@@ -1276,6 +1314,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + if (plane->state->normalized_zpos != zpos) + continue; + ++ vc4_plane_state = to_vc4_plane_state(plane->state); ++ + /* Is this the first active plane? */ + if (dlist_next == dlist_start) { + /* We need to enable background fill when a plane +@@ -1286,10 +1326,15 @@ void vc4_hvs_atomic_flush(struct drm_crt + * already needs it or all planes on top blend from + * the first or a lower plane. + */ +- vc4_plane_state = to_vc4_plane_state(plane->state); + enable_bg_fill = vc4_plane_state->needs_bg_fill; + } + ++ if (vc4_plane_state->lbm_size) { ++ vc4_plane_state->dlist[vc4_plane_state->lbm_offset] = ++ lbm_offset; ++ lbm_offset += vc4_plane_state->lbm_size; ++ } ++ + dlist_next += vc4_plane_write_dlist(plane, dlist_next); + + found = true; +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -288,7 +288,6 @@ struct drm_plane_state *vc4_plane_duplic + if (!vc4_state) + return NULL; + +- memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm)); + memset(&vc4_state->upm, 0, sizeof(vc4_state->upm)); + + for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) +@@ -320,14 +319,6 @@ void vc4_plane_destroy_state(struct drm_ + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + unsigned int i; + +- if (drm_mm_node_allocated(&vc4_state->lbm)) { +- unsigned long irqflags; +- +- spin_lock_irqsave(&hvs->mm_lock, irqflags); +- drm_mm_remove_node(&vc4_state->lbm); +- spin_unlock_irqrestore(&hvs->mm_lock, irqflags); +- } +- + for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) { + unsigned long irqflags; + +@@ -903,12 +894,13 @@ static int vc4_plane_allocate_lbm(struct + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct drm_plane *plane = state->plane; + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); +- unsigned long irqflags; + u32 lbm_size; + + lbm_size = vc4_lbm_size(state); +- if (!lbm_size) ++ if (!lbm_size) { ++ vc4_state->lbm_size = 0; + return 0; ++ } + + /* + * NOTE: BCM2712 doesn't need to be aligned, since the size +@@ -925,28 +917,10 @@ static int vc4_plane_allocate_lbm(struct + if (WARN_ON(!vc4_state->lbm_offset)) + return -EINVAL; + +- /* Allocate the LBM memory that the HVS will use for temporary +- * storage due to our scaling/format conversion. ++ /* FIXME: Add loop here that ensures that the total LBM assigned in this ++ * state is less than the total lbm size + */ +- if (!drm_mm_node_allocated(&vc4_state->lbm)) { +- int ret; +- +- spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); +- ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, +- &vc4_state->lbm, +- lbm_size, 1, +- 0, 0); +- spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); +- +- if (ret) { +- drm_err(drm, "Failed to allocate LBM entry: %d\n", ret); +- return ret; +- } +- } else { +- WARN_ON_ONCE(lbm_size != vc4_state->lbm.size); +- } +- +- vc4_state->dlist[vc4_state->lbm_offset] = vc4_state->lbm.start; ++ vc4_state->lbm_size = lbm_size; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0989-drm-panel-simple-Alter-the-timing-for-the-Pi-7-DSI-d.patch b/target/linux/bcm27xx/patches-6.1/950-0989-drm-panel-simple-Alter-the-timing-for-the-Pi-7-DSI-d.patch new file mode 100644 index 0000000000..ef70de7ee4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0989-drm-panel-simple-Alter-the-timing-for-the-Pi-7-DSI-d.patch @@ -0,0 +1,33 @@ +From b1bd2f406eab321be642decd6aee6b6222aec62b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 28 Jul 2023 17:40:27 +0100 +Subject: [PATCH] drm/panel: simple: Alter the timing for the Pi 7" DSI display + +vc4 has always fixed up the timing, so the values defined have +never actually appeared on the wire. +The display appears to want a slightly longer HFP, so extend +the timings and recompute the clock to give the same frame rate. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/panel/panel-simple.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/panel/panel-simple.c ++++ b/drivers/gpu/drm/panel/panel-simple.c +@@ -3241,11 +3241,11 @@ static const struct panel_desc qishenglo + }; + + static const struct drm_display_mode raspberrypi_7inch_mode = { +- .clock = 25979400 / 1000, ++ .clock = 27777, + .hdisplay = 800, +- .hsync_start = 800 + 2, +- .hsync_end = 800 + 2 + 2, +- .htotal = 800 + 2 + 2 + 46, ++ .hsync_start = 800 + 59, ++ .hsync_end = 800 + 59 + 2, ++ .htotal = 800 + 59 + 2 + 46, + .vdisplay = 480, + .vsync_start = 480 + 7, + .vsync_end = 480 + 7 + 2, diff --git a/target/linux/bcm27xx/patches-6.1/950-0990-drm-panel-waveshare-Fix-up-timings-for-10.1-panel.patch b/target/linux/bcm27xx/patches-6.1/950-0990-drm-panel-waveshare-Fix-up-timings-for-10.1-panel.patch new file mode 100644 index 0000000000..0a4203fbc5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0990-drm-panel-waveshare-Fix-up-timings-for-10.1-panel.patch @@ -0,0 +1,33 @@ +From c7cf33911d477fe55a91a9e4d84dad857b244ae3 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 28 Jul 2023 18:10:53 +0100 +Subject: [PATCH] drm/panel: waveshare: Fix up timings for 10.1" panel + +The 10.1" panel doesn't work with the timings defined. vc4 +will always have been fixing up the timing due to the limited +integer divider, so compute the fixed up mode and use it +directly. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -112,11 +112,11 @@ static const struct drm_display_mode ws_ + * https://www.waveshare.com/product/raspberry-pi/displays/10.1inch-dsi-lcd-c.htm + */ + static const struct drm_display_mode ws_panel_10_1_mode = { +- .clock = 76800, ++ .clock = 83333, + .hdisplay = 1280, +- .hsync_start = 1280 + 40, +- .hsync_end = 1280 + 40 + 20, +- .htotal = 1280 + 40 + 20 + 40, ++ .hsync_start = 1280 + 156, ++ .hsync_end = 1280 + 156 + 20, ++ .htotal = 1280 + 156 + 20 + 40, + .vdisplay = 800, + .vsync_start = 800 + 40, + .vsync_end = 800 + 40 + 48, diff --git a/target/linux/bcm27xx/patches-6.1/950-0991-media-i2c-imx477-Fix-locking-in-imx477_init_controls.patch b/target/linux/bcm27xx/patches-6.1/950-0991-media-i2c-imx477-Fix-locking-in-imx477_init_controls.patch new file mode 100644 index 0000000000..9d7869af9c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0991-media-i2c-imx477-Fix-locking-in-imx477_init_controls.patch @@ -0,0 +1,34 @@ +From 72c25bbb761de2b2acd9f8b652d63e2a2f1caeed Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Mon, 11 Sep 2023 12:17:25 +0300 +Subject: [PATCH] media: i2c: imx477: Fix locking in imx477_init_controls() + +The driver does not lock the imx477 mutex when calling +imx477_set_framing_limits(), leading to: + +WARNING: CPU: 3 PID: 426 at drivers/media/v4l2-core/v4l2-ctrls-api.c:934 __v4l2_ctrl_modify_range+0x1a0/0x210 [ +videodev] + +Fix this by taking the lock. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/i2c/imx477.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -2069,9 +2069,13 @@ static int imx477_init_controls(struct i + + imx477->sd.ctrl_handler = ctrl_hdlr; + ++ mutex_lock(&imx477->mutex); ++ + /* Setup exposure and frame/line length limits. */ + imx477_set_framing_limits(imx477); + ++ mutex_unlock(&imx477->mutex); ++ + return 0; + + error: diff --git a/target/linux/bcm27xx/patches-6.1/950-0994-overlays-Fix-vc4-kms-dsi-7inch.patch b/target/linux/bcm27xx/patches-6.1/950-0994-overlays-Fix-vc4-kms-dsi-7inch.patch new file mode 100644 index 0000000000..10339e2774 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0994-overlays-Fix-vc4-kms-dsi-7inch.patch @@ -0,0 +1,57 @@ +From 2ff65ffbdeb0c8764985af19df2a687a126136f4 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 29 Sep 2023 16:55:28 +0100 +Subject: [PATCH] overlays: Fix vc4-kms-dsi-7inch + +Fix the touchscreen. + +See: https://github.com/raspberrypi/linux/issues/5619 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 13 ++++--------- + .../boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts | 2 +- + 2 files changed, 5 insertions(+), 10 deletions(-) + +--- a/arch/arm/boot/dts/overlays/edt-ft5406.dtsi ++++ b/arch/arm/boot/dts/overlays/edt-ft5406.dtsi +@@ -22,11 +22,13 @@ + }; + }; + +- fragment@12 { +- target = <&i2cbus>; ++ ts_i2c_frag: fragment@12 { ++ target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; ++ status = "okay"; ++ + ft5406: ts@38 { + compatible = "edt,edt-ft5506"; + reg = <0x38>; +@@ -37,13 +39,6 @@ + }; + }; + +- ts_i2c_frag: fragment@13 { +- target = <&i2c_csi_dsi>; +- i2cbus: __overlay__ { +- status = "okay"; +- }; +- }; +- + __overrides__ { + sizex = <&ft5406>,"touchscreen-size-x:0"; + sizey = <&ft5406>,"touchscreen-size-y:0"; +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts +@@ -119,6 +119,6 @@ + <&panel_disp>, "reg:0=0", + <®_bridge>, "reg:0=0", + <®_bridge>, "regulator-name=bridge_reg_0"; +- disable_touch = <0>, "-10-11-12"; ++ disable_touch = <&ft5406>, "status=disabled"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0996-ASoC-hdmi-codec-Fix-broken-channel-map-reporting.patch b/target/linux/bcm27xx/patches-6.1/950-0996-ASoC-hdmi-codec-Fix-broken-channel-map-reporting.patch new file mode 100644 index 0000000000..c8fd2a2f90 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0996-ASoC-hdmi-codec-Fix-broken-channel-map-reporting.patch @@ -0,0 +1,56 @@ +From a1caea3c996f6bfa8c9568f521257f4e473285fb Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Fri, 29 Sep 2023 21:50:28 +0200 +Subject: [PATCH] ASoC: hdmi-codec: Fix broken channel map reporting + +Commit b84b53149476b22cc3b8677b771fb4cf06d1d455 upstream. + +Commit 4e0871333661 ("ASoC: hdmi-codec: fix channel info for +compressed formats") accidentally changed hcp->chmap_idx from +ca_id, the CEA channel allocation ID, to idx, the index to +the table of channel mappings ordered by preference. + +This resulted in wrong channel maps being reported to userspace, +eg for 5.1 "FL,FR,LFE,FC" was reported instead of the expected +"FL,FR,LFE,FC,RL,RR": + +~ # speaker-test -c 6 -t sine +... + 0 - Front Left + 3 - Front Center + 1 - Front Right + 2 - LFE + 4 - Unknown + 5 - Unknown + +~ # amixer cget iface=PCM,name='Playback Channel Map' | grep ': values' + : values=3,4,8,7,0,0,0,0 + +Switch this back to ca_id in case of PCM audio so the correct channel +map is reported again and set it to HDMI_CODEC_CHMAP_IDX_UNKNOWN in +case of non-PCM audio so the PCM channel map control returns "Unknown" +channels (value 0). + +Fixes: 4e0871333661 ("ASoC: hdmi-codec: fix channel info for compressed formats") +Cc: stable@vger.kernel.org +Signed-off-by: Matthias Reichl +Link: https://lore.kernel.org/r/20230929195027.97136-1-hias@horus.com +Signed-off-by: Mark Brown +--- + sound/soc/codecs/hdmi-codec.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -520,7 +520,10 @@ static int hdmi_codec_fill_codec_params( + hp->sample_rate = sample_rate; + hp->channels = channels; + +- hcp->chmap_idx = idx; ++ if (pcm_audio) ++ hcp->chmap_idx = ca_id; ++ else ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0997-media-rp1-cfe-Fix-use-of-freed-memory-on-errors.patch b/target/linux/bcm27xx/patches-6.1/950-0997-media-rp1-cfe-Fix-use-of-freed-memory-on-errors.patch new file mode 100644 index 0000000000..7f1b505336 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0997-media-rp1-cfe-Fix-use-of-freed-memory-on-errors.patch @@ -0,0 +1,48 @@ +From 3922bebc11fcc8459c798cfcb582828f9bbaa9e9 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 28 Sep 2023 11:33:53 +0300 +Subject: [PATCH] media: rp1: cfe: Fix use of freed memory on errors + +cfe_probe_complete() calls cfe_put() on both success and fail code paths. +This works for the success path, but causes the cfe_device struct to be +freed, even if it will be used later in the teardown code. + +Fix this by making the ref handling a bit saner: Let the video nodes +have the refs as they do now, but also keep a ref in the "main" driver, +released only at cfe_remove() time. This way the driver does not depend +on the video nodes keeping the refs. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -1837,17 +1837,10 @@ static int cfe_probe_complete(struct cfe + goto unregister; + } + +- /* +- * Release the initial reference, all references are now owned by the +- * video devices. +- */ +- cfe_put(cfe); + return 0; + + unregister: + cfe_unregister_nodes(cfe); +- cfe_put(cfe); +- + return ret; + } + +@@ -2129,6 +2122,8 @@ static int cfe_remove(struct platform_de + + v4l2_device_unregister(&cfe->v4l2_dev); + ++ cfe_put(cfe); ++ + return 0; + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0998-media-rp1-cfe-Fix-width-height-in-cfe_start_channel.patch b/target/linux/bcm27xx/patches-6.1/950-0998-media-rp1-cfe-Fix-width-height-in-cfe_start_channel.patch new file mode 100644 index 0000000000..d49856c32d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0998-media-rp1-cfe-Fix-width-height-in-cfe_start_channel.patch @@ -0,0 +1,88 @@ +From 84c9958dd71b8a4dcf16cbf6fdb867c668652634 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 27 Sep 2023 16:00:39 +0300 +Subject: [PATCH] media: rp1: cfe: Fix width & height in cfe_start_channel() + +The logic for handling width & height in cfe_start_channel() is somewhat +odd and, afaics, broken. The code reads: + +bool start_fe = is_fe_enabled(cfe) && + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); + +if (start_fe || is_image_output_node(node)) { + width = node->fmt.fmt.pix.width; + height = node->fmt.fmt.pix.height; +} + +cfe_start_channel() is called for all video nodes that will be used. So +this means that if, say, fe_stats is enabled as the last node, start_fe +will be true, and width and height will be taken from fe_stats' node. +The width and height will thus contain garbage, which then gets +programmed to the csi2 registers. + +It seems that this often still works fine, though, probably if the width +& height are large enough. + +Drop the above code, and instead get the width & height from the csi2 +subdev's sink pad for the csi2 channel that is used. For metadata the +width & height will be 0 as before. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -763,20 +763,16 @@ static void cfe_start_channel(struct cfe + struct v4l2_mbus_framefmt *source_fmt; + const struct cfe_fmt *fmt; + unsigned long flags; +- unsigned int width = 0, height = 0; + bool start_fe = is_fe_enabled(cfe) && + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +- if (start_fe || is_image_output_node(node)) { +- width = node->fmt.fmt.pix.width; +- height = node->fmt.fmt.pix.height; +- } +- + state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd); + + if (start_fe) { ++ unsigned int width, height; ++ + WARN_ON(!is_fe_enabled(cfe)); + cfe_dbg("%s: %s using csi2 channel %d\n", + __func__, node_desc[FE_OUT0].name, +@@ -785,6 +781,9 @@ static void cfe_start_channel(struct cfe + source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, cfe->fe_csi2_channel); + fmt = find_format_by_code(source_fmt->code); + ++ width = source_fmt->width; ++ height = source_fmt->height; ++ + /* + * Start the associated CSI2 Channel as well. + * +@@ -800,6 +799,8 @@ static void cfe_start_channel(struct cfe + } + + if (is_csi2_node(node)) { ++ unsigned int width = 0, height = 0; ++ + u32 mode = CSI2_MODE_NORMAL; + + source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, +@@ -807,6 +808,9 @@ static void cfe_start_channel(struct cfe + fmt = find_format_by_code(source_fmt->code); + + if (is_image_output_node(node)) { ++ width = source_fmt->width; ++ height = source_fmt->height; ++ + if (node->fmt.fmt.pix.pixelformat == + fmt->remap[CFE_REMAP_16BIT]) + mode = CSI2_MODE_REMAP; diff --git a/target/linux/bcm27xx/patches-6.1/950-0999-media-rp1-csi2-Fix-missing-reg-writes.patch b/target/linux/bcm27xx/patches-6.1/950-0999-media-rp1-csi2-Fix-missing-reg-writes.patch new file mode 100644 index 0000000000..2a3915b6e3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0999-media-rp1-csi2-Fix-missing-reg-writes.patch @@ -0,0 +1,36 @@ +From 62e8ab88d2c230dad122aabe2ad0e227d7ceba40 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 28 Sep 2023 10:42:22 +0300 +Subject: [PATCH] media: rp1: csi2: Fix missing reg writes + +The driver has two places where it writes a register based on a +condition, and when that condition is false, the driver presumes that +the register has the reset value. This is not a good idea, so fix those +places to always write the register. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/csi2.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -253,6 +253,7 @@ void csi2_start_channel(struct csi2_devi + */ + set_field(&ctrl, 0x3ff, LC_MASK); + set_field(&ctrl, 0x00, CH_MODE_MASK); ++ csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0); + } + + set_field(&ctrl, dt, DT_MASK); +@@ -277,8 +278,8 @@ void csi2_open_rx(struct csi2_device *cs + { + dphy_start(&csi2->dphy); + +- if (!csi2->multipacket_line) +- csi2_reg_write(csi2, CSI2_CTRL, EOP_IS_EOL); ++ csi2_reg_write(csi2, CSI2_CTRL, ++ csi2->multipacket_line ? 0 : EOP_IS_EOL); + } + + void csi2_close_rx(struct csi2_device *csi2) diff --git a/target/linux/bcm27xx/patches-6.1/950-1000-media-rp1-fe-Use-0-not-1-when-working-with-unsigned-.patch b/target/linux/bcm27xx/patches-6.1/950-1000-media-rp1-fe-Use-0-not-1-when-working-with-unsigned-.patch new file mode 100644 index 0000000000..f468b7ac48 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1000-media-rp1-fe-Use-0-not-1-when-working-with-unsigned-.patch @@ -0,0 +1,33 @@ +From 455c4ae2c70348a5842835d2f67f7cd8e665a2a6 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 21 Sep 2023 16:03:07 +0300 +Subject: [PATCH] media: rp1: fe: Use ~0, not -1, when working with unsigned + values + +Use ~0, not -1, when working with unsigned values (-1 is not unsigned). + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -372,7 +372,7 @@ void pisp_fe_submit_job(struct pisp_fe_d + void pisp_fe_start(struct pisp_fe_device *fe) + { + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_RESET); +- pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); + pisp_fe_reg_write(fe, FE_INT_EN, FE_INT_EOF | FE_INT_SOF | FE_INT_LINES0 | FE_INT_LINES1); + fe->inframe_count = 0; + } +@@ -383,7 +383,7 @@ void pisp_fe_stop(struct pisp_fe_device + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_ABORT); + usleep_range(1000, 2000); + WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); +- pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); + } + + static struct pisp_fe_device *to_pisp_fe_device(struct v4l2_subdev *subdev) diff --git a/target/linux/bcm27xx/patches-6.1/950-1001-media-rp1-cfe-Fix-verbose-debug-print.patch b/target/linux/bcm27xx/patches-6.1/950-1001-media-rp1-cfe-Fix-verbose-debug-print.patch new file mode 100644 index 0000000000..3344c32d29 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1001-media-rp1-cfe-Fix-verbose-debug-print.patch @@ -0,0 +1,26 @@ +From bf1709d2cf2b57c4ea98b8363156835249ae02cc Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 22 Sep 2023 12:41:35 +0300 +Subject: [PATCH] media: rp1: cfe: Fix verbose debug print + +The debug print in cfe_schedule_next_csi2_job() is printed every frame, +and should thus use cfe_dbg_irq() to avoid spamming, rather than cfe_dbg(). + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -518,8 +518,8 @@ static void cfe_schedule_next_csi2_job(s + node->next_frm = buf; + list_del(&buf->list); + +- cfe_dbg("%s: [%s] buffer:%p\n", +- __func__, node_desc[node->id].name, &buf->vb.vb2_buf); ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); + + if (is_meta_node(node)) { + size = node->fmt.fmt.meta.buffersize; diff --git a/target/linux/bcm27xx/patches-6.1/950-1002-media-rp1-cfe-Rename-xxx_dbg_irq-to-xxx_dbg_verbose.patch b/target/linux/bcm27xx/patches-6.1/950-1002-media-rp1-cfe-Rename-xxx_dbg_irq-to-xxx_dbg_verbose.patch new file mode 100644 index 0000000000..14fa0447df --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1002-media-rp1-cfe-Rename-xxx_dbg_irq-to-xxx_dbg_verbose.patch @@ -0,0 +1,227 @@ +From a1ea528e187ee045aeff929ff0f4b2e53fdd970f Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 4 Oct 2023 10:12:37 +0300 +Subject: [PATCH] media: rp1: cfe: Rename xxx_dbg_irq() to xxx_dbg_verbose() + +Rename the xxx_dbg_irq() macros to xxx_dbg_verbose(), as they can be +used to verbose debugs outside irq context too. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 40 +++++++++---------- + .../media/platform/raspberrypi/rp1_cfe/cfe.h | 2 +- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 26 ++++++------ + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 12 +++--- + 4 files changed, 40 insertions(+), 40 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -49,11 +49,11 @@ + #define CFE_MODULE_NAME "rp1-cfe" + #define CFE_VERSION "1.0" + +-bool cfe_debug_irq; ++bool cfe_debug_verbose; + +-#define cfe_dbg_irq(fmt, arg...) \ ++#define cfe_dbg_verbose(fmt, arg...) \ + do { \ +- if (cfe_debug_irq) \ ++ if (cfe_debug_verbose) \ + dev_dbg(&cfe->pdev->dev, fmt, ##arg); \ + } while (0) + #define cfe_dbg(fmt, arg...) dev_dbg(&cfe->pdev->dev, fmt, ##arg) +@@ -518,8 +518,8 @@ static void cfe_schedule_next_csi2_job(s + node->next_frm = buf; + list_del(&buf->list); + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, +- node_desc[node->id].name, &buf->vb.vb2_buf); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); + + if (is_meta_node(node)) { + size = node->fmt.fmt.meta.buffersize; +@@ -550,8 +550,8 @@ static void cfe_schedule_next_pisp_job(s + buf = list_first_entry(&node->dma_queue, struct cfe_buffer, + list); + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, +- node_desc[node->id].name, &buf->vb.vb2_buf); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); + + node->next_frm = buf; + vb2_bufs[node_desc[i].link_pad] = &buf->vb.vb2_buf; +@@ -573,8 +573,8 @@ static bool cfe_check_job_ready(struct c + continue; + + if (list_empty(&node->dma_queue)) { +- cfe_dbg_irq("%s: [%s] has no buffer, unable to schedule job\n", +- __func__, node_desc[i].name); ++ cfe_dbg_verbose("%s: [%s] has no buffer, unable to schedule job\n", ++ __func__, node_desc[i].name); + return false; + } + } +@@ -592,7 +592,7 @@ static void cfe_prepare_next_job(struct + /* Flag if another job is ready after this. */ + cfe->job_ready = cfe_check_job_ready(cfe); + +- cfe_dbg_irq("%s: end with scheduled job\n", __func__); ++ cfe_dbg_verbose("%s: end with scheduled job\n", __func__); + } + + static void cfe_process_buffer_complete(struct cfe_node *node, +@@ -600,8 +600,8 @@ static void cfe_process_buffer_complete( + { + struct cfe_device *cfe = node->cfe; + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, +- &node->cur_frm->vb.vb2_buf); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &node->cur_frm->vb.vb2_buf); + + node->cur_frm->vb.sequence = sequence; + vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); +@@ -621,8 +621,8 @@ static void cfe_sof_isr_handler(struct c + { + struct cfe_device *cfe = node->cfe; + +- cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); ++ cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); + + node->cur_frm = node->next_frm; + node->next_frm = NULL; +@@ -651,8 +651,8 @@ static void cfe_eof_isr_handler(struct c + { + struct cfe_device *cfe = node->cfe; + +- cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); ++ cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); + + if (node->cur_frm) + cfe_process_buffer_complete(node, cfe->sequence); +@@ -921,8 +921,8 @@ static int cfe_buffer_prepare(struct vb2 + struct cfe_buffer *buf = to_cfe_buffer(vb); + unsigned long size; + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, +- vb); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, vb); + + size = is_image_output_node(node) ? node->fmt.fmt.pix.sizeimage : + node->fmt.fmt.meta.buffersize; +@@ -954,8 +954,8 @@ static void cfe_buffer_queue(struct vb2_ + struct cfe_buffer *buf = to_cfe_buffer(vb); + unsigned long flags; + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, +- vb); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, vb); + + spin_lock_irqsave(&cfe->state_lock, flags); + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -11,7 +11,7 @@ + #include + #include + +-extern bool cfe_debug_irq; ++extern bool cfe_debug_verbose; + + enum cfe_remap_types { + CFE_REMAP_16BIT, +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -16,9 +16,9 @@ + #include "csi2.h" + #include "cfe.h" + +-#define csi2_dbg_irq(fmt, arg...) \ ++#define csi2_dbg_verbose(fmt, arg...) \ + do { \ +- if (cfe_debug_irq) \ ++ if (cfe_debug_verbose) \ + dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg); \ + } while (0) + #define csi2_dbg(fmt, arg...) dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg) +@@ -154,7 +154,7 @@ void csi2_isr(struct csi2_device *csi2, + u32 status; + + status = csi2_reg_read(csi2, CSI2_STATUS); +- csi2_dbg_irq("ISR: STA: 0x%x\n", status); ++ csi2_dbg_verbose("ISR: STA: 0x%x\n", status); + + /* Write value back to clear the interrupts */ + csi2_reg_write(csi2, CSI2_STATUS, status); +@@ -167,16 +167,16 @@ void csi2_isr(struct csi2_device *csi2, + + dbg = csi2_reg_read(csi2, CSI2_CH_DEBUG(i)); + +- csi2_dbg_irq("ISR: [%u], %s%s%s%s%s frame: %u line: %u\n", i, +- (status & IRQ_FS(i)) ? "FS " : "", +- (status & IRQ_FE(i)) ? "FE " : "", +- (status & IRQ_FE_ACK(i)) ? "FE_ACK " : "", +- (status & IRQ_LE(i)) ? "LE " : "", +- (status & IRQ_LE_ACK(i)) ? "LE_ACK " : "", +- dbg >> 16, +- csi2->num_lines[i] ? +- ((dbg & 0xffff) % csi2->num_lines[i]) : +- 0); ++ csi2_dbg_verbose("ISR: [%u], %s%s%s%s%s frame: %u line: %u\n", ++ i, (status & IRQ_FS(i)) ? "FS " : "", ++ (status & IRQ_FE(i)) ? "FE " : "", ++ (status & IRQ_FE_ACK(i)) ? "FE_ACK " : "", ++ (status & IRQ_LE(i)) ? "LE " : "", ++ (status & IRQ_LE_ACK(i)) ? "LE_ACK " : "", ++ dbg >> 16, ++ csi2->num_lines[i] ? ++ ((dbg & 0xffff) % csi2->num_lines[i]) : ++ 0); + + sof[i] = !!(status & IRQ_FS(i)); + eof[i] = !!(status & IRQ_FE_ACK(i)); +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -114,9 +114,9 @@ static const struct pisp_fe_config_param + sizeof(struct pisp_fe_output_config) }, + }; + +-#define pisp_fe_dbg_irq(fmt, arg...) \ ++#define pisp_fe_dbg_verbose(fmt, arg...) \ + do { \ +- if (cfe_debug_irq) \ ++ if (cfe_debug_verbose) \ + dev_dbg(fe->v4l2_dev->dev, fmt, ##arg); \ + } while (0) + #define pisp_fe_dbg(fmt, arg...) dev_dbg(fe->v4l2_dev->dev, fmt, ##arg) +@@ -202,9 +202,9 @@ void pisp_fe_isr(struct pisp_fe_device * + int_status = pisp_fe_reg_read(fe, FE_INT_STATUS); + pisp_fe_reg_write(fe, FE_INT_STATUS, int_status); + +- pisp_fe_dbg_irq("%s: status 0x%x out 0x%x frame 0x%x error 0x%x int 0x%x\n", +- __func__, status, out_status, frame_status, error_status, +- int_status); ++ pisp_fe_dbg_verbose("%s: status 0x%x out 0x%x frame 0x%x error 0x%x int 0x%x\n", ++ __func__, status, out_status, frame_status, error_status, ++ int_status); + + /* We do not report interrupts for the input/stream pad. */ + for (i = 0; i < FE_NUM_PADS - 1; i++) { +@@ -339,7 +339,7 @@ void pisp_fe_submit_job(struct pisp_fe_d + * sequence of relaxed writes which follow. + */ + status = pisp_fe_reg_read(fe, FE_STATUS); +- pisp_fe_dbg_irq("%s: status = 0x%x\n", __func__, status); ++ pisp_fe_dbg_verbose("%s: status = 0x%x\n", __func__, status); + if (WARN_ON(status & FE_STATUS_QUEUED)) + return; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1003-media-rp1-Add-back-reg-write-debug-prints.patch b/target/linux/bcm27xx/patches-6.1/950-1003-media-rp1-Add-back-reg-write-debug-prints.patch new file mode 100644 index 0000000000..c86f7a3e17 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1003-media-rp1-Add-back-reg-write-debug-prints.patch @@ -0,0 +1,41 @@ +From 8240f1328ead0152f116b385b3169f8f010a7869 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 22 Sep 2023 12:39:33 +0300 +Subject: [PATCH] media: rp1: Add back reg write debug prints + +Add back debug prints in csi2 and pisp_fe reg_write() functions, but use +the 'irq' variants to avoid spamming in normal situation. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/csi2.c | 1 + + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 2 ++ + 2 files changed, 3 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -92,6 +92,7 @@ static inline u32 csi2_reg_read(struct c + static inline void csi2_reg_write(struct csi2_device *csi2, u32 offset, u32 val) + { + writel(val, csi2->base + offset); ++ csi2_dbg_verbose("csi2: write 0x%04x -> 0x%03x\n", val, offset); + } + + static inline void set_field(u32 *valp, u32 field, u32 mask) +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -132,12 +132,14 @@ static inline void pisp_fe_reg_write(str + u32 val) + { + writel(val, fe->base + offset); ++ pisp_fe_dbg_verbose("fe: write 0x%04x -> 0x%03x\n", val, offset); + } + + static inline void pisp_fe_reg_write_relaxed(struct pisp_fe_device *fe, u32 offset, + u32 val) + { + writel_relaxed(val, fe->base + offset); ++ pisp_fe_dbg_verbose("fe: write 0x%04x -> 0x%03x\n", val, offset); + } + + static int pisp_regs_show(struct seq_file *s, void *data) diff --git a/target/linux/bcm27xx/patches-6.1/950-1004-media-rp1-cfe-Add-verbose-debug-module-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-1004-media-rp1-cfe-Add-verbose-debug-module-parameter.patch new file mode 100644 index 0000000000..f44cb50d10 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1004-media-rp1-cfe-Add-verbose-debug-module-parameter.patch @@ -0,0 +1,23 @@ +From f2553458c0c1942731447aac3878f51aa1b326a7 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 4 Oct 2023 10:19:47 +0300 +Subject: [PATCH] media: rp1: cfe: Add verbose debug module parameter + +Expose the verbose debug flag as a module parameter. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -50,6 +50,8 @@ + #define CFE_VERSION "1.0" + + bool cfe_debug_verbose; ++module_param_named(verbose_debug, cfe_debug_verbose, bool, 0644); ++MODULE_PARM_DESC(verbose_debug, "verbose debugging messages"); + + #define cfe_dbg_verbose(fmt, arg...) \ + do { \ diff --git a/target/linux/bcm27xx/patches-6.1/950-1005-media-rp1-csi2-Track-CSI-2-errors.patch b/target/linux/bcm27xx/patches-6.1/950-1005-media-rp1-csi2-Track-CSI-2-errors.patch new file mode 100644 index 0000000000..9d8da81887 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1005-media-rp1-csi2-Track-CSI-2-errors.patch @@ -0,0 +1,245 @@ +From b19c2b5f88f141e58044e5d1012f867d46f74bf3 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 21 Sep 2023 18:18:53 +0300 +Subject: [PATCH] media: rp1: csi2: Track CSI-2 errors + +Track the errors from the CSI-2 receiver: overflows and discards. These +are recorded in a table which can be read by the userspace via debugfs. + +As tracking the errors may cause much more interrupt load, the tracking +needs to be enabled with a module parameter. + +Note that the recording is not perfect: we only record the last +discarded DT for each discard type, instead of recording all of them. +This means that e.g. if the device is discarding two unmatched DTs, the +debugfs file only shows the last one recorded. Recording all of them +would need a more sophisticated recording system to avoid the need of a +very large table, or dynamic allocation. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 123 ++++++++++++++++++ + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 16 +++ + 2 files changed, 139 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -16,6 +16,10 @@ + #include "csi2.h" + #include "cfe.h" + ++static bool csi2_track_errors; ++module_param_named(track_csi2_errors, csi2_track_errors, bool, 0); ++MODULE_PARM_DESC(track_csi2_errors, "track csi-2 errors"); ++ + #define csi2_dbg_verbose(fmt, arg...) \ + do { \ + if (cfe_debug_verbose) \ +@@ -32,9 +36,28 @@ + #define CSI2_DISCARDS_INACTIVE 0x00c + #define CSI2_DISCARDS_UNMATCHED 0x010 + #define CSI2_DISCARDS_LEN_LIMIT 0x014 ++ ++#define CSI2_DISCARDS_AMOUNT_SHIFT 0 ++#define CSI2_DISCARDS_AMOUNT_MASK GENMASK(23, 0) ++#define CSI2_DISCARDS_DT_SHIFT 24 ++#define CSI2_DISCARDS_DT_MASK GENMASK(29, 24) ++#define CSI2_DISCARDS_VC_SHIFT 30 ++#define CSI2_DISCARDS_VC_MASK GENMASK(31, 30) ++ + #define CSI2_LLEV_PANICS 0x018 + #define CSI2_ULEV_PANICS 0x01c + #define CSI2_IRQ_MASK 0x020 ++#define CSI2_IRQ_MASK_IRQ_OVERFLOW BIT(0) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_OVERFLOW BIT(1) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_LENGTH_LIMIT BIT(2) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_UNMATCHED BIT(3) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_INACTIVE BIT(4) ++#define CSI2_IRQ_MASK_IRQ_ALL \ ++ (CSI2_IRQ_MASK_IRQ_OVERFLOW | CSI2_IRQ_MASK_IRQ_DISCARD_OVERFLOW | \ ++ CSI2_IRQ_MASK_IRQ_DISCARD_LENGTH_LIMIT | \ ++ CSI2_IRQ_MASK_IRQ_DISCARD_UNMATCHED | \ ++ CSI2_IRQ_MASK_IRQ_DISCARD_INACTIVE) ++ + #define CSI2_CTRL 0x024 + #define CSI2_CH_CTRL(x) ((x) * 0x40 + 0x28) + #define CSI2_CH_ADDR0(x) ((x) * 0x40 + 0x2c) +@@ -149,6 +172,92 @@ static int csi2_regs_show(struct seq_fil + + DEFINE_SHOW_ATTRIBUTE(csi2_regs); + ++static int csi2_errors_show(struct seq_file *s, void *data) ++{ ++ struct csi2_device *csi2 = s->private; ++ unsigned long flags; ++ u32 discards_table[DISCARDS_TABLE_NUM_VCS][DISCARDS_TABLE_NUM_ENTRIES]; ++ u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES]; ++ u32 overflows; ++ ++ spin_lock_irqsave(&csi2->errors_lock, flags); ++ ++ memcpy(discards_table, csi2->discards_table, sizeof(discards_table)); ++ memcpy(discards_dt_table, csi2->discards_dt_table, ++ sizeof(discards_dt_table)); ++ overflows = csi2->overflows; ++ ++ csi2->overflows = 0; ++ memset(csi2->discards_table, 0, sizeof(discards_table)); ++ memset(csi2->discards_dt_table, 0, sizeof(discards_dt_table)); ++ ++ spin_unlock_irqrestore(&csi2->errors_lock, flags); ++ ++ seq_printf(s, "Overflows %u\n", overflows); ++ seq_puts(s, "Discards:\n"); ++ seq_puts(s, "VC OVLF LEN UNMATCHED INACTIVE\n"); ++ ++ for (unsigned int vc = 0; vc < DISCARDS_TABLE_NUM_VCS; ++vc) { ++ seq_printf(s, "%u %10u %10u %10u %10u\n", vc, ++ discards_table[vc][DISCARDS_TABLE_OVERFLOW], ++ discards_table[vc][DISCARDS_TABLE_LENGTH_LIMIT], ++ discards_table[vc][DISCARDS_TABLE_UNMATCHED], ++ discards_table[vc][DISCARDS_TABLE_INACTIVE]); ++ } ++ ++ seq_printf(s, "Last DT %10u %10u %10u %10u\n", ++ discards_dt_table[DISCARDS_TABLE_OVERFLOW], ++ discards_dt_table[DISCARDS_TABLE_LENGTH_LIMIT], ++ discards_dt_table[DISCARDS_TABLE_UNMATCHED], ++ discards_dt_table[DISCARDS_TABLE_INACTIVE]); ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(csi2_errors); ++ ++static void csi2_isr_handle_errors(struct csi2_device *csi2, u32 status) ++{ ++ spin_lock(&csi2->errors_lock); ++ ++ if (status & IRQ_OVERFLOW) ++ csi2->overflows++; ++ ++ for (unsigned int i = 0; i < DISCARDS_TABLE_NUM_ENTRIES; ++i) { ++ static const u32 discard_bits[] = { ++ IRQ_DISCARD_OVERFLOW, ++ IRQ_DISCARD_LEN_LIMIT, ++ IRQ_DISCARD_UNMATCHED, ++ IRQ_DISCARD_INACTIVE, ++ }; ++ static const u8 discard_regs[] = { ++ CSI2_DISCARDS_OVERFLOW, ++ CSI2_DISCARDS_LEN_LIMIT, ++ CSI2_DISCARDS_UNMATCHED, ++ CSI2_DISCARDS_INACTIVE, ++ }; ++ u32 amount; ++ u8 dt, vc; ++ u32 v; ++ ++ if (!(status & discard_bits[i])) ++ continue; ++ ++ v = csi2_reg_read(csi2, discard_regs[i]); ++ csi2_reg_write(csi2, discard_regs[i], 0); ++ ++ amount = (v & CSI2_DISCARDS_AMOUNT_MASK) >> ++ CSI2_DISCARDS_AMOUNT_SHIFT; ++ dt = (v & CSI2_DISCARDS_DT_MASK) >> CSI2_DISCARDS_DT_SHIFT; ++ vc = (v & CSI2_DISCARDS_VC_MASK) >> CSI2_DISCARDS_VC_SHIFT; ++ ++ csi2->discards_table[vc][i] += amount; ++ csi2->discards_dt_table[i] = dt; ++ } ++ ++ spin_unlock(&csi2->errors_lock); ++} ++ + void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci) + { + unsigned int i; +@@ -183,6 +292,9 @@ void csi2_isr(struct csi2_device *csi2, + eof[i] = !!(status & IRQ_FE_ACK(i)); + lci[i] = !!(status & IRQ_LE_ACK(i)); + } ++ ++ if (csi2_track_errors) ++ csi2_isr_handle_errors(csi2, status); + } + + void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, +@@ -277,6 +389,9 @@ void csi2_stop_channel(struct csi2_devic + + void csi2_open_rx(struct csi2_device *csi2) + { ++ csi2_reg_write(csi2, CSI2_IRQ_MASK, ++ csi2_track_errors ? CSI2_IRQ_MASK_IRQ_ALL : 0); ++ + dphy_start(&csi2->dphy); + + csi2_reg_write(csi2, CSI2_CTRL, +@@ -286,6 +401,8 @@ void csi2_open_rx(struct csi2_device *cs + void csi2_close_rx(struct csi2_device *csi2) + { + dphy_stop(&csi2->dphy); ++ ++ csi2_reg_write(csi2, CSI2_IRQ_MASK, 0); + } + + static struct csi2_device *to_csi2_device(struct v4l2_subdev *subdev) +@@ -398,11 +515,17 @@ int csi2_init(struct csi2_device *csi2, + { + unsigned int i, ret; + ++ spin_lock_init(&csi2->errors_lock); ++ + csi2->dphy.dev = csi2->v4l2_dev->dev; + dphy_probe(&csi2->dphy); + + debugfs_create_file("csi2_regs", 0444, debugfs, csi2, &csi2_regs_fops); + ++ if (csi2_track_errors) ++ debugfs_create_file("csi2_errors", 0444, debugfs, csi2, ++ &csi2_errors_fops); ++ + for (i = 0; i < CSI2_NUM_CHANNELS * 2; i++) + csi2->pad[i].flags = i < CSI2_NUM_CHANNELS ? + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -17,6 +17,8 @@ + + #define CSI2_NUM_CHANNELS 4 + ++#define DISCARDS_TABLE_NUM_VCS 4 ++ + enum csi2_mode { + CSI2_MODE_NORMAL, + CSI2_MODE_REMAP, +@@ -37,6 +39,14 @@ struct csi2_cfg { + u32 buffer_size; + }; + ++enum discards_table_index { ++ DISCARDS_TABLE_OVERFLOW = 0, ++ DISCARDS_TABLE_LENGTH_LIMIT, ++ DISCARDS_TABLE_UNMATCHED, ++ DISCARDS_TABLE_INACTIVE, ++ DISCARDS_TABLE_NUM_ENTRIES, ++}; ++ + struct csi2_device { + /* Parent V4l2 device */ + struct v4l2_device *v4l2_dev; +@@ -53,6 +63,12 @@ struct csi2_device { + + struct media_pad pad[CSI2_NUM_CHANNELS * 2]; + struct v4l2_subdev sd; ++ ++ /* lock for csi2 errors counters */ ++ spinlock_t errors_lock; ++ u32 overflows; ++ u32 discards_table[DISCARDS_TABLE_NUM_VCS][DISCARDS_TABLE_NUM_ENTRIES]; ++ u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES]; + }; + + void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci); diff --git a/target/linux/bcm27xx/patches-6.1/950-1006-media-rp1-cfe-Drop-unused-field.patch b/target/linux/bcm27xx/patches-6.1/950-1006-media-rp1-cfe-Drop-unused-field.patch new file mode 100644 index 0000000000..b53a5b6154 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1006-media-rp1-cfe-Drop-unused-field.patch @@ -0,0 +1,31 @@ +From d6bd676b49cf10046665efde820b0cc00dc43994 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 28 Sep 2023 17:04:07 +0300 +Subject: [PATCH] media: rp1: cfe: Drop unused field + +Drop 'sensor_embedded_data' field, as it is unused. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -292,7 +292,6 @@ struct cfe_device { + struct csi2_device csi2; + struct pisp_fe_device fe; + +- bool sensor_embedded_data; + int fe_csi2_channel; + + unsigned int sequence; +@@ -1821,8 +1820,6 @@ static int cfe_probe_complete(struct cfe + + cfe->v4l2_dev.notify = cfe_notify; + +- cfe->sensor_embedded_data = (cfe->sensor->entity.num_pads >= 2); +- + for (i = 0; i < NUM_NODES; i++) { + ret = cfe_register_node(cfe, i); + if (ret) { diff --git a/target/linux/bcm27xx/patches-6.1/950-1007-media-rp1-csi2-Set-values-for-enum-csi2_mode.patch b/target/linux/bcm27xx/patches-6.1/950-1007-media-rp1-csi2-Set-values-for-enum-csi2_mode.patch new file mode 100644 index 0000000000..126ee2c493 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1007-media-rp1-csi2-Set-values-for-enum-csi2_mode.patch @@ -0,0 +1,30 @@ +From c56b53d62116b4672962124afab02f3beada4244 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 12:57:23 +0300 +Subject: [PATCH] media: rp1: csi2: Set values for enum csi2_mode + +Set hardcoded values for enum csi2_mode, as the values will be +programmed to HW registers. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/csi2.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -20,10 +20,10 @@ + #define DISCARDS_TABLE_NUM_VCS 4 + + enum csi2_mode { +- CSI2_MODE_NORMAL, +- CSI2_MODE_REMAP, +- CSI2_MODE_COMPRESSED, +- CSI2_MODE_FE_STREAMING ++ CSI2_MODE_NORMAL = 0, ++ CSI2_MODE_REMAP = 1, ++ CSI2_MODE_COMPRESSED = 2, ++ CSI2_MODE_FE_STREAMING = 3, + }; + + enum csi2_compression_mode { diff --git a/target/linux/bcm27xx/patches-6.1/950-1008-media-rp1-fe-Fix-default-mbus-code.patch b/target/linux/bcm27xx/patches-6.1/950-1008-media-rp1-fe-Fix-default-mbus-code.patch new file mode 100644 index 0000000000..e4ea9e1d16 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1008-media-rp1-fe-Fix-default-mbus-code.patch @@ -0,0 +1,27 @@ +From 5edacf33de9e0349dd5a02ad684bfceae1d5565f Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 13:29:15 +0300 +Subject: [PATCH] media: rp1: fe: Fix default mbus code + +When pisp_fe_pad_set_fmt() is given an mbus code that CFE does not +support, it currently defaults to MEDIA_BUS_FMT_SBGGR10_1X10. This is +not correct, as FE does not support SBGGR10. + +Set the default to MEDIA_BUS_FMT_SRGGB16_1X16 instead. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -437,7 +437,7 @@ static int pisp_fe_pad_set_fmt(struct v4 + case FE_OUTPUT1_PAD: + cfe_fmt = find_format_by_code(format->format.code); + if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) +- cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16); + + format->format.code = cfe_fmt->code; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1009-media-rp1-cfe-Fix-default-meta-format-s-field.patch b/target/linux/bcm27xx/patches-6.1/950-1009-media-rp1-cfe-Fix-default-meta-format-s-field.patch new file mode 100644 index 0000000000..2ac5e0e88a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1009-media-rp1-cfe-Fix-default-meta-format-s-field.patch @@ -0,0 +1,25 @@ +From 47fd9528bc1d93dd07ce9baa19c736966b536bd9 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Mon, 2 Oct 2023 14:38:07 +0300 +Subject: [PATCH] media: rp1: cfe: Fix default meta format's field + +Set default meta format's field to V4L2_FIELD_NONE, instead of zeroing +it which indicates V4L2_FIELD_ANY. Metadata doesn't have fields, so NONE +makes sense, and furthermore the default v4l2 link validation will check +for matching fields, or that the sink field is NONE. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -110,6 +110,7 @@ const struct v4l2_mbus_framefmt cfe_defa + .width = 8192, + .height = 1, + .code = MEDIA_BUS_FMT_SENSOR_DATA, ++ .field = V4L2_FIELD_NONE, + }; + + enum node_ids { diff --git a/target/linux/bcm27xx/patches-6.1/950-1010-media-rp1-cfe-Fail-streaming-if-FE_CONFIG-node-is-no.patch b/target/linux/bcm27xx/patches-6.1/950-1010-media-rp1-cfe-Fail-streaming-if-FE_CONFIG-node-is-no.patch new file mode 100644 index 0000000000..de469c3565 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1010-media-rp1-cfe-Fail-streaming-if-FE_CONFIG-node-is-no.patch @@ -0,0 +1,31 @@ +From 3e2203b265ddd8630fea0fbb69b3a2ec1496f773 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 4 Oct 2023 09:39:59 +0100 +Subject: [PATCH] media: rp1: cfe: Fail streaming if FE_CONFIG node is not + enabled + +When the FE is enabled, ensure that the FE_CONFIG node is enabled. +Otherwise fail cfe_start_streaming() entirely. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -997,6 +997,14 @@ static int cfe_start_streaming(struct vb + goto err_streaming; + } + ++ /* When using the Frontend, we must enable the FE_CONFIG node. */ ++ if (is_fe_enabled(cfe) && ++ !check_state(cfe, NODE_ENABLED, cfe->node[FE_CONFIG].id)) { ++ cfe_err("FE enabled, but FE_CONFIG node is not\n"); ++ ret = -EINVAL; ++ goto err_streaming; ++ } ++ + ret = media_pipeline_start(&node->pad, &cfe->pipe); + if (ret < 0) { + cfe_err("Failed to start media pipeline: %d\n", ret); diff --git a/target/linux/bcm27xx/patches-6.1/950-1011-media-i2c-Move-Kconfig-entry-for-IMX477-to-the-camer.patch b/target/linux/bcm27xx/patches-6.1/950-1011-media-i2c-Move-Kconfig-entry-for-IMX477-to-the-camer.patch new file mode 100644 index 0000000000..37e1a86e16 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1011-media-i2c-Move-Kconfig-entry-for-IMX477-to-the-camer.patch @@ -0,0 +1,51 @@ +From 52811174f534824f5e5bcdb681f0c508aa335244 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 4 Oct 2023 11:09:10 +0100 +Subject: [PATCH] media: i2c: Move Kconfig entry for IMX477 to the camera + sensor section + +It was accidentally placed in the audio decoder section. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/Kconfig | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -270,6 +270,17 @@ config VIDEO_IMX412 + To compile this driver as a module, choose M here: the + module will be called imx412. + ++config VIDEO_IMX477 ++ tristate "Sony IMX477 sensor support" ++ depends on I2C && VIDEO_DEV ++ select VIDEO_V4L2_SUBDEV_API ++ help ++ This is a Video4Linux2 sensor driver for the Sony ++ IMX477 camera. Also supports the Sony IMX378. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called imx477. ++ + config VIDEO_IMX519 + tristate "Arducam IMX519 sensor support" + depends on I2C && VIDEO_DEV +@@ -1106,17 +1117,6 @@ config VIDEO_UDA1342 + To compile this driver as a module, choose M here: the + module will be called uda1342. + +-config VIDEO_IMX477 +- tristate "Sony IMX477 sensor support" +- depends on I2C && VIDEO_DEV +- select VIDEO_V4L2_SUBDEV_API +- help +- This is a Video4Linux2 sensor driver for the Sony +- IMX477 camera. Also supports the Sony IMX378. +- +- To compile this driver as a module, choose M here: the +- module will be called imx477. +- + config VIDEO_VP27SMPX + tristate "Panasonic VP27's internal MPX" + depends on VIDEO_DEV && I2C diff --git a/target/linux/bcm27xx/patches-6.1/950-1013-drm-Look-for-an-alias-for-the-displays-to-use-as-the.patch b/target/linux/bcm27xx/patches-6.1/950-1013-drm-Look-for-an-alias-for-the-displays-to-use-as-the.patch new file mode 100644 index 0000000000..8de6c372c0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1013-drm-Look-for-an-alias-for-the-displays-to-use-as-the.patch @@ -0,0 +1,109 @@ +From 3aa1f2477545ea6298bc6f2d7ffae68f090af9b8 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 28 Sep 2023 18:27:09 +0100 +Subject: [PATCH] drm: Look for an alias for the displays to use as the DRM + device name + +Allow DT aliases of eg DSI2 to force make DRM allocate the +display with the requested name. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_connector.c | 60 ++++++++++++++++++++++++++++++--- + 1 file changed, 56 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -81,6 +81,7 @@ struct drm_conn_prop_enum_list { + int type; + const char *name; + struct ida ida; ++ int first_dyn_num; + }; + + /* +@@ -110,12 +111,41 @@ static struct drm_conn_prop_enum_list dr + { DRM_MODE_CONNECTOR_USB, "USB" }, + }; + ++#define MAX_DT_NODE_NAME_LEN 20 ++#define DT_DRM_NODE_PREFIX "drm_" ++ ++static void drm_connector_get_of_name(int type, char *node_name, int length) ++{ ++ int i = 0; ++ ++ strcpy(node_name, DT_DRM_NODE_PREFIX); ++ ++ do { ++ node_name[i + strlen(DT_DRM_NODE_PREFIX)] = ++ tolower(drm_connector_enum_list[type].name[i]); ++ ++ } while (drm_connector_enum_list[type].name[i++] && ++ i < length); ++ ++ node_name[length - 1] = '\0'; ++} ++ + void drm_connector_ida_init(void) + { +- int i; ++ int i, id; ++ char node_name[MAX_DT_NODE_NAME_LEN]; + +- for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) ++ for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) { + ida_init(&drm_connector_enum_list[i].ida); ++ ++ drm_connector_get_of_name(i, node_name, MAX_DT_NODE_NAME_LEN); ++ ++ id = of_alias_get_highest_id(node_name); ++ if (id > 0) ++ drm_connector_enum_list[i].first_dyn_num = id + 1; ++ else ++ drm_connector_enum_list[i].first_dyn_num = 1; ++ } + } + + void drm_connector_ida_destroy(void) +@@ -222,7 +252,9 @@ static int __drm_connector_init(struct d + struct i2c_adapter *ddc) + { + struct drm_mode_config *config = &dev->mode_config; ++ char node_name[MAX_DT_NODE_NAME_LEN]; + int ret; ++ int id; + struct ida *connector_ida = + &drm_connector_enum_list[connector_type].ida; + +@@ -252,8 +284,28 @@ static int __drm_connector_init(struct d + ret = 0; + + connector->connector_type = connector_type; +- connector->connector_type_id = +- ida_alloc_min(connector_ida, 1, GFP_KERNEL); ++ connector->connector_type_id = 0; ++ ++ drm_connector_get_of_name(connector_type, node_name, MAX_DT_NODE_NAME_LEN); ++ id = of_alias_get_id(dev->dev->of_node, node_name); ++ if (id > 0) { ++ /* Try and allocate the requested ID ++ * Valid range is 1 to 31, hence ignoring 0 as an error ++ */ ++ int type_id = ida_alloc_range(connector_ida, id, id, GFP_KERNEL); ++ ++ if (type_id > 0) ++ connector->connector_type_id = type_id; ++ else ++ drm_err(dev, "Failed to acquire type ID %d for interface type %s, ret %d\n", ++ id, drm_connector_enum_list[connector_type].name, ++ type_id); ++ } ++ if (!connector->connector_type_id) ++ connector->connector_type_id = ++ ida_alloc_min(connector_ida, ++ drm_connector_enum_list[connector_type].first_dyn_num, ++ GFP_KERNEL); + if (connector->connector_type_id < 0) { + ret = connector->connector_type_id; + goto out_put_id; diff --git a/target/linux/bcm27xx/patches-6.1/950-1014-dt-Add-DSI1-and-DSI2-aliases-to-2712.patch b/target/linux/bcm27xx/patches-6.1/950-1014-dt-Add-DSI1-and-DSI2-aliases-to-2712.patch new file mode 100644 index 0000000000..6d79cb6c4d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1014-dt-Add-DSI1-and-DSI2-aliases-to-2712.patch @@ -0,0 +1,24 @@ +From 7ec42740a45b21bca859cde5b7cbe2f09ef3d586 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 28 Sep 2023 18:40:36 +0100 +Subject: [PATCH] dt: Add DSI1 and DSI2 aliases to 2712 + +In order to keep the DRM names consistent as DSI-1 and DSI-2, add +aliases to the Pi5 DT. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -785,6 +785,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + gpio4 = &pinctrl_aon; + usb0 = &rp1_usb0; + usb1 = &rp1_usb1; ++ drm_dsi1 = &dsi0; ++ drm_dsi2 = &dsi1; + }; + + __overrides__ { diff --git a/target/linux/bcm27xx/patches-6.1/950-1015-vc4-drm-Remove-the-clear-of-SCALER_DISPBKGND_FILL.patch b/target/linux/bcm27xx/patches-6.1/950-1015-vc4-drm-Remove-the-clear-of-SCALER_DISPBKGND_FILL.patch new file mode 100644 index 0000000000..a4c8aeadd3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1015-vc4-drm-Remove-the-clear-of-SCALER_DISPBKGND_FILL.patch @@ -0,0 +1,64 @@ +From e6e0631fdeb0cd7d4c50e629b4b298e0b76e885b Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 4 Oct 2023 16:02:39 +0100 +Subject: [PATCH] vc4/drm: Remove the clear of SCALER_DISPBKGND_FILL + +Since "drm/vc4: hvs: Support BCM2712 HVS" booting Pi4 +with dual 4kp30 displays connected fails with: +vc4-drm gpu: [drm] *ERROR* [CRTC:107:pixelvalve-4] flip_done timed out + +It has been tracked down to the referenced commit adding a +path to clear the SCALER_DISPBKGND_FILL when not required. + +Dual 4kp30 works with a core clock of 297MHz when background fill +is enabled, but requires a higher value with it disabled. +320MHz still fails, while 330MHz seems okay. + +Lets always enable background fill for Pi0-4. + +Fixes: e84da235223d ("drm/vc4: hvs: Support BCM2712 HVS") + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1349,27 +1349,25 @@ void vc4_hvs_atomic_flush(struct drm_crt + WARN_ON(!vc4_state->mm); + WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm->mm_node.size); + +- if (enable_bg_fill) { ++ if (vc4->gen >= VC4_GEN_6) { + /* This sets a black background color fill, as is the case + * with other DRM drivers. + */ +- if (vc4->gen >= VC4_GEN_6) ++ if (enable_bg_fill) + HVS_WRITE(SCALER6_DISPX_CTRL1(channel), + HVS_READ(SCALER6_DISPX_CTRL1(channel)) | + SCALER6_DISPX_CTRL1_BGENB); + else +- HVS_WRITE(SCALER_DISPBKGNDX(channel), +- HVS_READ(SCALER_DISPBKGNDX(channel)) | +- SCALER_DISPBKGND_FILL); +- } else { +- if (vc4->gen >= VC4_GEN_6) + HVS_WRITE(SCALER6_DISPX_CTRL1(channel), + HVS_READ(SCALER6_DISPX_CTRL1(channel)) & + ~SCALER6_DISPX_CTRL1_BGENB); +- else +- HVS_WRITE(SCALER_DISPBKGNDX(channel), +- HVS_READ(SCALER_DISPBKGNDX(channel)) & +- ~SCALER_DISPBKGND_FILL); ++ } else { ++ /* we can actually run with a lower core clock when background ++ * fill is enabled on VC4_GEN_5 so leave it enabled always. ++ */ ++ HVS_WRITE(SCALER_DISPBKGNDX(channel), ++ HVS_READ(SCALER_DISPBKGNDX(channel)) | ++ SCALER_DISPBKGND_FILL); + } + + /* Only update DISPLIST if the CRTC was already running and is not diff --git a/target/linux/bcm27xx/patches-6.1/950-1017-gpio-brcmstb-Use-dynamic-GPIO-base-numbers.patch b/target/linux/bcm27xx/patches-6.1/950-1017-gpio-brcmstb-Use-dynamic-GPIO-base-numbers.patch new file mode 100644 index 0000000000..9bf9e6d96d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1017-gpio-brcmstb-Use-dynamic-GPIO-base-numbers.patch @@ -0,0 +1,117 @@ +From 450d617786926b27c25e930241efbd2e37d66bb8 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 6 Oct 2023 16:30:35 +0100 +Subject: [PATCH] gpio: brcmstb: Use dynamic GPIO base numbers + +Forcing a gpiochip to have a fixed base number now leads to a warning +message. Remove the need to do so by calculating hwirq numbers based +on bank numbers. + +Signed-off-by: Phil Elwell +Fixes: 3b0213d56eb7 ("gpio: Add GPIO support for Broadcom STB SoCs") +--- + drivers/gpio/gpio-brcmstb.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +--- a/drivers/gpio/gpio-brcmstb.c ++++ b/drivers/gpio/gpio-brcmstb.c +@@ -50,7 +50,6 @@ struct brcmstb_gpio_priv { + struct irq_domain *irq_domain; + struct irq_chip irq_chip; + int parent_irq; +- int gpio_base; + int num_gpios; + int parent_wake_irq; + }; +@@ -92,7 +91,7 @@ brcmstb_gpio_get_active_irqs(struct brcm + static int brcmstb_gpio_hwirq_to_offset(irq_hw_number_t hwirq, + struct brcmstb_gpio_bank *bank) + { +- return hwirq - (bank->gc.base - bank->parent_priv->gpio_base); ++ return hwirq - bank->id * 32; + } + + static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, +@@ -117,8 +116,9 @@ static void brcmstb_gpio_set_imask(struc + static int brcmstb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) + { + struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); ++ struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); + /* gc_offset is relative to this gpio_chip; want real offset */ +- int hwirq = offset + (gc->base - priv->gpio_base); ++ int hwirq = offset + bank->id * 32; + + if (hwirq >= priv->num_gpios) + return -ENXIO; +@@ -263,7 +263,7 @@ static void brcmstb_gpio_irq_bank_handle + { + struct brcmstb_gpio_priv *priv = bank->parent_priv; + struct irq_domain *domain = priv->irq_domain; +- int hwbase = bank->gc.base - priv->gpio_base; ++ int hwbase = bank->id * 32; + unsigned long status; + + while ((status = brcmstb_gpio_get_active_irqs(bank))) { +@@ -414,7 +414,7 @@ static int brcmstb_gpio_of_xlate(struct + if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) + return -EINVAL; + +- offset = gpiospec->args[0] - (gc->base - priv->gpio_base); ++ offset = gpiospec->args[0] - bank->id * 32; + if (offset >= gc->ngpio || offset < 0) + return -EINVAL; + +@@ -598,8 +598,8 @@ static int brcmstb_gpio_probe(struct pla + const __be32 *p; + u32 bank_width; + int num_banks = 0; ++ int num_gpios = 0; + int err; +- static int gpio_base; + unsigned long flags = 0; + bool need_wakeup_event = false; + +@@ -614,7 +614,6 @@ static int brcmstb_gpio_probe(struct pla + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + +- priv->gpio_base = gpio_base; + priv->reg_base = reg_base; + priv->pdev = pdev; + +@@ -656,7 +655,7 @@ static int brcmstb_gpio_probe(struct pla + dev_dbg(dev, "Width 0 found: Empty bank @ %d\n", + num_banks); + num_banks++; +- gpio_base += MAX_GPIO_PER_BANK; ++ num_gpios += MAX_GPIO_PER_BANK; + continue; + } + +@@ -698,7 +697,7 @@ static int brcmstb_gpio_probe(struct pla + err = -ENOMEM; + goto fail; + } +- gc->base = gpio_base; ++ gc->base = -1; + gc->of_gpio_n_cells = 2; + gc->of_xlate = brcmstb_gpio_of_xlate; + /* not all ngpio lines are valid, will use bank width later */ +@@ -722,7 +721,7 @@ static int brcmstb_gpio_probe(struct pla + bank->id); + goto fail; + } +- gpio_base += gc->ngpio; ++ num_gpios += gc->ngpio; + + dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id, + gc->base, gc->ngpio, bank->width); +@@ -733,7 +732,7 @@ static int brcmstb_gpio_probe(struct pla + num_banks++; + } + +- priv->num_gpios = gpio_base - priv->gpio_base; ++ priv->num_gpios = num_gpios; + if (priv->parent_irq > 0) { + err = brcmstb_gpio_irq_setup(pdev, priv); + if (err) diff --git a/target/linux/bcm27xx/patches-6.1/950-1018-media-rpivid-Allow-use-of-iommu-in-rpivid.patch b/target/linux/bcm27xx/patches-6.1/950-1018-media-rpivid-Allow-use-of-iommu-in-rpivid.patch new file mode 100644 index 0000000000..a6d199a8c7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1018-media-rpivid-Allow-use-of-iommu-in-rpivid.patch @@ -0,0 +1,57 @@ +From 1770efc97981dbf756a18f5eb7615c4bafab665b Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Mon, 2 Oct 2023 15:12:52 +0100 +Subject: [PATCH] media/rpivid: Allow use of iommu in rpivid + +In order to use iommu on hevc set dma mask_and_coherent in probe. +I am assured dma_set_mask_and_coherent is benign on Pi4 (which has +no iommu) and it seems to be so in practice. +Also adds a bit of debug to make internal buffer allocation failure +easier to spot in future + +Signed-off-by: John Cox +--- + drivers/staging/media/rpivid/rpivid.c | 7 +++++++ + drivers/staging/media/rpivid/rpivid_h265.c | 12 ++++++++++-- + 2 files changed, 17 insertions(+), 2 deletions(-) + +--- a/drivers/staging/media/rpivid/rpivid.c ++++ b/drivers/staging/media/rpivid/rpivid.c +@@ -360,6 +360,13 @@ static int rpivid_probe(struct platform_ + snprintf(vfd->name, sizeof(vfd->name), "%s", rpivid_video_device.name); + video_set_drvdata(vfd, dev); + ++ ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(36)); ++ if (ret) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed dma_set_mask_and_coherent\n"); ++ goto err_v4l2; ++ } ++ + dev->m2m_dev = v4l2_m2m_init(&rpivid_m2m_ops); + if (IS_ERR(dev->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, +--- a/drivers/staging/media/rpivid/rpivid_h265.c ++++ b/drivers/staging/media/rpivid/rpivid_h265.c +@@ -2495,11 +2495,19 @@ static int rpivid_h265_start(struct rpiv + for (i = 0; i != ARRAY_SIZE(ctx->pu_bufs); ++i) { + // Don't actually need a kernel mapping here + if (gptr_alloc(dev, ctx->pu_bufs + i, pu_alloc, +- DMA_ATTR_NO_KERNEL_MAPPING)) ++ DMA_ATTR_NO_KERNEL_MAPPING)) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed to alloc %#zx PU%d buffer\n", ++ pu_alloc, i); + goto fail; ++ } + if (gptr_alloc(dev, ctx->coeff_bufs + i, coeff_alloc, +- DMA_ATTR_NO_KERNEL_MAPPING)) ++ DMA_ATTR_NO_KERNEL_MAPPING)) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed to alloc %#zx Coeff%d buffer\n", ++ pu_alloc, i); + goto fail; ++ } + } + aux_q_init(ctx); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1019-dts-bcm2712-Add-iommu-to-rpivid.patch b/target/linux/bcm27xx/patches-6.1/950-1019-dts-bcm2712-Add-iommu-to-rpivid.patch new file mode 100644 index 0000000000..9f7c8674fb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1019-dts-bcm2712-Add-iommu-to-rpivid.patch @@ -0,0 +1,22 @@ +From 10ff8ba24c68f704ecf5a58878617dfe149a14c6 Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Mon, 2 Oct 2023 15:15:13 +0100 +Subject: [PATCH] dts/bcm2712: Add iommu to rpivid + +Add iommu to rpivid so it can cope with scatter/gather + +Signed-off-by: John Cox +--- + arch/arm/boot/dts/bcm2712.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -1158,6 +1158,7 @@ + clocks = <&firmware_clocks 11>; + clock-names = "hevc"; + status = "disabled"; ++ iommus = <&iommu2>; + }; + + sdio1: mmc@fff000 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1020-drivers-media-rp1_cfe-Remove-PISP-specific-MBUS-form.patch b/target/linux/bcm27xx/patches-6.1/950-1020-drivers-media-rp1_cfe-Remove-PISP-specific-MBUS-form.patch new file mode 100644 index 0000000000..fabc96e422 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1020-drivers-media-rp1_cfe-Remove-PISP-specific-MBUS-form.patch @@ -0,0 +1,117 @@ +From b5c3cc7fd9fca73352310e61092fb445b56a362a Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 10 Oct 2023 12:41:15 +0100 +Subject: [PATCH] drivers: media: rp1_cfe: Remove PISP specific MBUS formats + +Remove the MEDIA_BUS_FMT_PISP* format codcs entirely. For the image +pad formats, use the 16-bit Bayer format mbus codes instead. For the +config and stats pad formats, use MEDIA_BUS_FMT_FIXED. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 10 ++++++---- + .../media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 11 ++++------- + include/uapi/linux/media-bus-format.h | 14 -------------- + 3 files changed, 10 insertions(+), 25 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -215,25 +215,25 @@ static const struct cfe_fmt formats[] = + /* PiSP Compressed Mode 1 */ + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB, +- .code = MEDIA_BUS_FMT_PISP_COMP1_RGGB, ++ .code = MEDIA_BUS_FMT_SRGGB16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR, +- .code = MEDIA_BUS_FMT_PISP_COMP1_BGGR, ++ .code = MEDIA_BUS_FMT_SBGGR16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG, +- .code = MEDIA_BUS_FMT_PISP_COMP1_GBRG, ++ .code = MEDIA_BUS_FMT_SGBRG16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG, +- .code = MEDIA_BUS_FMT_PISP_COMP1_GRBG, ++ .code = MEDIA_BUS_FMT_SGRBG16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, +@@ -283,10 +283,12 @@ static const struct cfe_fmt formats[] = + /* Frontend formats */ + { + .fourcc = V4L2_META_FMT_RPI_FE_CFG, ++ .code = MEDIA_BUS_FMT_FIXED, + .flags = CFE_FORMAT_FLAG_META_OUT, + }, + { + .fourcc = V4L2_META_FMT_RPI_FE_STATS, ++ .code = MEDIA_BUS_FMT_FIXED, + .flags = CFE_FORMAT_FLAG_META_CAP, + }, + }; +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -404,7 +404,7 @@ static int pisp_fe_init_cfg(struct v4l2_ + + fmt = v4l2_subdev_get_pad_format(sd, state, FE_CONFIG_PAD); + *fmt = cfe_default_meta_format; +- fmt->code = MEDIA_BUS_FMT_PISP_FE_CONFIG; ++ fmt->code = MEDIA_BUS_FMT_FIXED; + + fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT0_PAD); + *fmt = cfe_default_format; +@@ -416,7 +416,7 @@ static int pisp_fe_init_cfg(struct v4l2_ + + fmt = v4l2_subdev_get_pad_format(sd, state, FE_STATS_PAD); + *fmt = cfe_default_meta_format; +- fmt->code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ fmt->code = MEDIA_BUS_FMT_FIXED; + + return 0; + } +@@ -443,12 +443,9 @@ static int pisp_fe_pad_set_fmt(struct v4 + + break; + +- case FE_CONFIG_PAD: +- format->format.code = MEDIA_BUS_FMT_PISP_FE_CONFIG; +- break; +- + case FE_STATS_PAD: +- format->format.code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ case FE_CONFIG_PAD: ++ format->format.code = MEDIA_BUS_FMT_FIXED; + break; + } + +--- a/include/uapi/linux/media-bus-format.h ++++ b/include/uapi/linux/media-bus-format.h +@@ -175,18 +175,4 @@ + /* Sensor ancillary metadata formats - next is 0x7002 */ + #define MEDIA_BUS_FMT_SENSOR_DATA 0x7002 + +-/* PiSP Formats */ +-#define MEDIA_BUS_FMT_PISP_COMP1_RGGB 0x8001 +-#define MEDIA_BUS_FMT_PISP_COMP1_GRBG 0x8002 +-#define MEDIA_BUS_FMT_PISP_COMP1_GBRG 0x8003 +-#define MEDIA_BUS_FMT_PISP_COMP1_BGGR 0x8004 +-#define MEDIA_BUS_FMT_PISP_COMP2_RGGB 0x8005 +-#define MEDIA_BUS_FMT_PISP_COMP2_GRBG 0x8006 +-#define MEDIA_BUS_FMT_PISP_COMP2_GBRG 0x8007 +-#define MEDIA_BUS_FMT_PISP_COMP2_BGGR 0x8008 +- +-#define MEDIA_BUS_FMT_PISP_FE_CONFIG 0x8100 +-#define MEDIA_BUS_FMT_PISP_FE_STATS 0x8101 +-#define MEDIA_BUS_FMT_PISP_BE_CONFIG 0x8200 +- + #endif /* __LINUX_MEDIA_BUS_FORMAT_H */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1022-vc04_services-bcm2835-codec-Correct-alignment-requir.patch b/target/linux/bcm27xx/patches-6.1/950-1022-vc04_services-bcm2835-codec-Correct-alignment-requir.patch new file mode 100644 index 0000000000..313ca37738 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1022-vc04_services-bcm2835-codec-Correct-alignment-requir.patch @@ -0,0 +1,53 @@ +From 9f4002165439d02a63760e68948246e3af764318 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 11 Oct 2023 15:05:38 +0100 +Subject: [PATCH] vc04_services: bcm2835-codec: Correct alignment requirements + for YUYV + +The firmware wants the YUYV format stride alignment to be to a multiple +of 32pixels / 64 bytes. The kernel driver was configuring it to a multiple +of 16 pixels / 32 bytes, which then failed when it tried starting to +stream. + +Correct the alignment requirements. + +Signed-off-by: Dave Stevenson +--- + .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c ++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +@@ -206,28 +206,28 @@ static const struct bcm2835_codec_fmt su + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_YUYV, + .size_multiplier_x2 = 2, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_UYVY, + .size_multiplier_x2 = 2, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_YVYU, + .size_multiplier_x2 = 2, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_VYUY, + .size_multiplier_x2 = 2, diff --git a/target/linux/bcm27xx/patches-6.1/950-1025-input-touchscreen-edt-ft5x06-Suppress-bogus-data-on-.patch b/target/linux/bcm27xx/patches-6.1/950-1025-input-touchscreen-edt-ft5x06-Suppress-bogus-data-on-.patch new file mode 100644 index 0000000000..fe956c2ed4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1025-input-touchscreen-edt-ft5x06-Suppress-bogus-data-on-.patch @@ -0,0 +1,96 @@ +From dd802fc03b1c71b4297e87068077bfcf9810300a Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 11 Oct 2023 15:14:59 +0100 +Subject: [PATCH] input: touchscreen: edt-ft5x06: Suppress bogus data on + startup + +When polled without the use of IRQ, FT5x06 registers may return +undefined initial data, causing unwanted touches or event spamming. +A simple way to filter this out is to suppress touches until the +TD_STATUS register changes for the first time. + +Increase the delay before first polling to 300ms, to avoid +transient I2C read flakiness that seems to occur after reset. + +Signed-off-by: Nick Hollinghurst +--- + drivers/input/touchscreen/edt-ft5x06.c | 31 +++++++++++++++++++++++--- + 1 file changed, 28 insertions(+), 3 deletions(-) + +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -75,6 +75,8 @@ + #define EDT_DEFAULT_NUM_X 1024 + #define EDT_DEFAULT_NUM_Y 1024 + ++#define RESET_DELAY_MS 300 /* reset deassert to I2C */ ++#define FIRST_POLL_DELAY_MS 300 /* in addition to the above */ + #define POLL_INTERVAL_MS 17 /* 17ms = 60fps */ + + enum edt_pmode { +@@ -134,6 +136,7 @@ struct edt_ft5x06_ts_data { + + char name[EDT_NAME_LEN]; + char fw_version[EDT_NAME_LEN]; ++ int init_td_status; + + struct edt_reg_addr reg_addr; + enum edt_ver version; +@@ -268,12 +271,33 @@ static irqreturn_t edt_ft5x06_ts_isr(int + * points. + */ + num_points = min(rdbuf[2] & 0xf, tsdata->max_support_points); ++ ++ /* When polling FT5x06 without IRQ: initial register contents ++ * could be stale or undefined; discard all readings until ++ * TD_STATUS changes for the first time (or num_points is 0). ++ */ ++ if (tsdata->init_td_status) { ++ if (tsdata->init_td_status < 0) ++ tsdata->init_td_status = rdbuf[2]; ++ ++ if (num_points && rdbuf[2] == tsdata->init_td_status) ++ goto out; ++ ++ tsdata->init_td_status = 0; ++ } ++ + if (num_points) { + datalen = tplen * num_points + crclen; + cmd = offset; + error = edt_ft5x06_ts_readwrite(tsdata->client, + sizeof(cmd), &cmd, + datalen, &rdbuf[offset]); ++ if (error) { ++ dev_err_ratelimited(dev, ++ "Unable to fetch data, error: %d\n", ++ error); ++ goto out; ++ } + } + } + +@@ -1294,7 +1318,7 @@ static int edt_ft5x06_ts_probe(struct i2 + if (tsdata->reset_gpio) { + usleep_range(5000, 6000); + gpiod_set_value_cansleep(tsdata->reset_gpio, 0); +- msleep(300); ++ msleep(RESET_DELAY_MS); + } + + input = devm_input_allocate_device(&client->dev); +@@ -1384,11 +1408,12 @@ static int edt_ft5x06_ts_probe(struct i2 + return error; + } + } else { ++ tsdata->init_td_status = -1; /* filter bogus initial data */ + INIT_WORK(&tsdata->work_i2c_poll, + edt_ft5x06_ts_work_i2c_poll); + timer_setup(&tsdata->timer, edt_ft5x06_ts_irq_poll_timer, 0); +- tsdata->timer.expires = jiffies + +- msecs_to_jiffies(POLL_INTERVAL_MS); ++ tsdata->timer.expires = ++ jiffies + msecs_to_jiffies(FIRST_POLL_DELAY_MS); + add_timer(&tsdata->timer); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1029-overlays-mcp23017-allow-specification-of-the-i2c-bus.patch b/target/linux/bcm27xx/patches-6.1/950-1029-overlays-mcp23017-allow-specification-of-the-i2c-bus.patch new file mode 100644 index 0000000000..8cb35e1a79 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1029-overlays-mcp23017-allow-specification-of-the-i2c-bus.patch @@ -0,0 +1,97 @@ +From 27f0e0e195568c06f21ce380f0736bdd219baf3c Mon Sep 17 00:00:00 2001 +From: Janis Streib +Date: Sun, 15 Oct 2023 21:08:40 +0200 +Subject: [PATCH] overlays: mcp23017: allow specification of the i2c bus + +Analogous to i2c-rtc-overlay.dts + +See: https://github.com/raspberrypi/linux/pull/5650 +--- + arch/arm/boot/dts/overlays/README | 10 ++++++ + .../boot/dts/overlays/mcp23017-overlay.dts | 36 +++++++++++++++++-- + 2 files changed, 44 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2810,6 +2810,16 @@ Params: gpiopin Gpio pin + + mcp23008 Configure an MCP23008 instead. + noints Disable the interrupt GPIO line. ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c3 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c4 Choose the I2C4 bus (configure with the i2c4 ++ overlay - BCM2711 only) ++ i2c5 Choose the I2C5 bus (configure with the i2c5 ++ overlay - BCM2711 only) ++ i2c6 Choose the I2C6 bus (configure with the i2c6 ++ overlay - BCM2711 only) + + + Name: mcp23s17 +--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts +@@ -7,7 +7,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2c1>; ++ target = <&i2cbus>; + __overlay__ { + status = "okay"; + }; +@@ -24,7 +24,7 @@ + }; + + fragment@2 { +- target = <&i2c1>; ++ target = <&i2cbus>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; +@@ -58,12 +58,44 @@ + }; + }; + ++ frag100: fragment@100 { ++ target = <&i2c1>; ++ i2cbus: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@102 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + gpiopin = <&mcp23017_pins>,"brcm,pins:0", + <&mcp23017_irq>,"interrupts:0"; + addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0"; + mcp23008 = <0>,"=3"; + noints = <0>,"!1!4"; ++ i2c0 = <&frag100>, "target:0=",<&i2c0>; ++ i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+101+102"; ++ i2c3 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c3"; ++ i2c4 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c4"; ++ i2c5 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c5"; ++ i2c6 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c6"; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1030-dts-bcm2712-Set-default-I2C-baudrates-to-100kHz.patch b/target/linux/bcm27xx/patches-6.1/950-1030-dts-bcm2712-Set-default-I2C-baudrates-to-100kHz.patch new file mode 100644 index 0000000000..e9422f1daa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1030-dts-bcm2712-Set-default-I2C-baudrates-to-100kHz.patch @@ -0,0 +1,46 @@ +From 0339c8c61ca6b54c529f699e7bafd65cda9f3733 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 16 Oct 2023 09:06:25 +0100 +Subject: [PATCH] dts: bcm2712: Set default I2C baudrates to 100kHz + +The RP1 I2C interfaces were being left with their default clock rates, +apparently 400kHz. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + arch/arm/boot/dts/bcm2712-rpi.dtsi | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -250,11 +250,13 @@ i2c0mux: &rp1_gpio {}; + 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 +--- a/arch/arm/boot/dts/bcm2712-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2712-rpi.dtsi +@@ -204,11 +204,13 @@ uart4: &rp1_uart4 { }; + i2c_vc: &i2c0 { // This is pins 27,28 on the header (not MIPI) + pinctrl-0 = <&rp1_i2c0_0_1>; + pinctrl-names = "default"; ++ clock-frequency = <100000>; + }; + + i2c_arm: &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&rp1_i2c1_2_3>; ++ clock-frequency = <100000>; + }; + + &i2c2 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1031-vc_mem-Add-the-DMA-memcpy-support-from-bcm2708_fb.patch b/target/linux/bcm27xx/patches-6.1/950-1031-vc_mem-Add-the-DMA-memcpy-support-from-bcm2708_fb.patch new file mode 100644 index 0000000000..23d428789f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1031-vc_mem-Add-the-DMA-memcpy-support-from-bcm2708_fb.patch @@ -0,0 +1,345 @@ +From 2a47ccf97c6a91bc56f8cfb387d47f59cc347dd5 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Sat, 14 Oct 2023 14:57:49 +0100 +Subject: [PATCH] vc_mem: Add the DMA memcpy support from bcm2708_fb + +bcm2708_fb is disabled by the vc4-kms-v3d overlay, which means that the +DMA memcpy support it provides is not available to allow vclog to read +the VC logs from the top 16MB on Pi 2 and Pi 3. Add the code to the +vc_mem driver, which will still be enabled. + +It ought to be possible to do a proper DMA_MEM_TO_MEM copy via the +generic DMA customer API, but that can be a later step. + +Signed-off-by: Phil Elwell +--- + drivers/char/broadcom/vc_mem.c | 259 +++++++++++++++++++++++++++++++++ + 1 file changed, 259 insertions(+) + +--- a/drivers/char/broadcom/vc_mem.c ++++ b/drivers/char/broadcom/vc_mem.c +@@ -23,9 +23,21 @@ + #include + #include + #include ++#include ++#include ++#include + + #define DRIVER_NAME "vc-mem" + ++/* N.B. These use a different magic value for compatibility with bmc7208_fb */ ++#define VC_MEM_IOC_DMACOPY _IOW('z', 0x22, struct vc_mem_dmacopy) ++#define VC_MEM_IOC_DMACOPY32 _IOW('z', 0x22, struct vc_mem_dmacopy32) ++ ++/* address with no aliases */ ++#define INTALIAS_NORMAL(x) ((x) & ~0xc0000000) ++/* cache coherent but non-allocating in L1 and L2 */ ++#define INTALIAS_L1L2_NONALLOCATING(x) (((x) & ~0xc0000000) | 0x80000000) ++ + /* Device (/dev) related variables */ + static dev_t vc_mem_devnum; + static struct class *vc_mem_class; +@@ -36,6 +48,20 @@ static int vc_mem_inited; + static struct dentry *vc_mem_debugfs_entry; + #endif + ++struct vc_mem_dmacopy { ++ void *dst; ++ __u32 src; ++ __u32 length; ++}; ++ ++#ifdef CONFIG_COMPAT ++struct vc_mem_dmacopy32 { ++ compat_uptr_t dst; ++ __u32 src; ++ __u32 length; ++}; ++#endif ++ + /* + * Videocore memory addresses and size + * +@@ -62,6 +88,20 @@ static uint phys_addr; + static uint mem_size; + static uint mem_base; + ++struct vc_mem_dma { ++ struct device *dev; ++ int dma_chan; ++ int dma_irq; ++ void __iomem *dma_chan_base; ++ wait_queue_head_t dma_waitq; ++ void *cb_base; /* DMA control blocks */ ++ dma_addr_t cb_handle; ++}; ++ ++struct { u32 base, length; } gpu_mem; ++static struct mutex dma_mutex; ++static struct vc_mem_dma vc_mem_dma; ++ + static int + vc_mem_open(struct inode *inode, struct file *file) + { +@@ -99,6 +139,189 @@ vc_mem_get_current_size(void) + } + EXPORT_SYMBOL_GPL(vc_mem_get_current_size); + ++static int ++vc_mem_dma_init(void) ++{ ++ struct vc_mem_dma *vcdma = &vc_mem_dma; ++ struct platform_device *pdev; ++ struct device_node *fwnode; ++ struct rpi_firmware *fw; ++ struct device *dev; ++ u32 revision; ++ int rc; ++ ++ if (vcdma->dev) ++ return 0; ++ ++ fwnode = of_find_node_by_path("/system"); ++ rc = of_property_read_u32(fwnode, "linux,revision", &revision); ++ revision = (revision >> 12) & 0xf; ++ if (revision != 1 && revision != 2) { ++ /* Only BCM2709 and BCM2710 may have logs where the ARMs ++ * can't see them. ++ */ ++ return -ENXIO; ++ } ++ ++ fwnode = rpi_firmware_find_node(); ++ if (!fwnode) ++ return -ENXIO; ++ ++ pdev = of_find_device_by_node(fwnode); ++ dev = &pdev->dev; ++ ++ rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); ++ if (rc) ++ return rc; ++ ++ fw = rpi_firmware_get(fwnode); ++ if (!fw) ++ return -ENXIO; ++ rc = rpi_firmware_property(fw, RPI_FIRMWARE_GET_VC_MEMORY, ++ &gpu_mem, sizeof(gpu_mem)); ++ if (rc) ++ return rc; ++ ++ gpu_mem.base = INTALIAS_NORMAL(gpu_mem.base); ++ ++ if (!gpu_mem.base || !gpu_mem.length) { ++ dev_err(dev, "%s: unable to determine gpu memory (%x,%x)\n", ++ __func__, gpu_mem.base, gpu_mem.length); ++ return -EFAULT; ++ } ++ ++ vcdma->cb_base = dma_alloc_wc(dev, SZ_4K, &vcdma->cb_handle, GFP_KERNEL); ++ if (!vcdma->cb_base) { ++ dev_err(dev, "failed to allocate DMA CBs\n"); ++ return -ENOMEM; ++ } ++ ++ rc = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK, ++ &vcdma->dma_chan_base, ++ &vcdma->dma_irq); ++ if (rc < 0) { ++ dev_err(dev, "failed to allocate a DMA channel\n"); ++ goto free_cb; ++ } ++ ++ vcdma->dma_chan = rc; ++ ++ init_waitqueue_head(&vcdma->dma_waitq); ++ ++ vcdma->dev = dev; ++ ++ return 0; ++ ++free_cb: ++ dma_free_wc(dev, SZ_4K, vcdma->cb_base, vcdma->cb_handle); ++ ++ return rc; ++} ++ ++static void ++vc_mem_dma_uninit(void) ++{ ++ struct vc_mem_dma *vcdma = &vc_mem_dma; ++ ++ if (vcdma->dev) { ++ bcm_dma_chan_free(vcdma->dma_chan); ++ dma_free_wc(vcdma->dev, SZ_4K, vcdma->cb_base, vcdma->cb_handle); ++ vcdma->dev = NULL; ++ } ++} ++ ++static int dma_memcpy(struct vc_mem_dma *vcdma, dma_addr_t dst, dma_addr_t src, ++ int size) ++{ ++ struct bcm2708_dma_cb *cb = vcdma->cb_base; ++ int burst_size = (vcdma->dma_chan == 0) ? 8 : 2; ++ ++ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | ++ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | ++ BCM2708_DMA_D_INC; ++ cb->dst = dst; ++ cb->src = src; ++ cb->length = size; ++ cb->stride = 0; ++ cb->pad[0] = 0; ++ cb->pad[1] = 0; ++ cb->next = 0; ++ ++ bcm_dma_start(vcdma->dma_chan_base, vcdma->cb_handle); ++ bcm_dma_wait_idle(vcdma->dma_chan_base); ++ ++ return 0; ++} ++ ++static long vc_mem_copy(struct vc_mem_dmacopy *ioparam) ++{ ++ struct vc_mem_dma *vcdma = &vc_mem_dma; ++ size_t size = PAGE_SIZE; ++ const u32 dma_xfer_chunk = 256; ++ u32 *buf = NULL; ++ dma_addr_t bus_addr; ++ long rc = 0; ++ size_t offset; ++ ++ /* restrict this to root user */ ++ if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) ++ return -EFAULT; ++ ++ if (mutex_lock_interruptible(&dma_mutex)) ++ return -EINTR; ++ ++ rc = vc_mem_dma_init(); ++ if (rc) ++ goto out; ++ ++ vcdma = &vc_mem_dma; ++ ++ if (INTALIAS_NORMAL(ioparam->src) < gpu_mem.base || ++ INTALIAS_NORMAL(ioparam->src) >= gpu_mem.base + gpu_mem.length) { ++ pr_err("%s: invalid memory access %x (%x-%x)", __func__, ++ INTALIAS_NORMAL(ioparam->src), gpu_mem.base, ++ gpu_mem.base + gpu_mem.length); ++ rc = -EFAULT; ++ goto out; ++ } ++ ++ buf = dma_alloc_coherent(vcdma->dev, PAGE_ALIGN(size), &bus_addr, ++ GFP_ATOMIC); ++ if (!buf) { ++ rc = -ENOMEM; ++ goto out; ++ } ++ ++ for (offset = 0; offset < ioparam->length; offset += size) { ++ size_t remaining = ioparam->length - offset; ++ size_t s = min(size, remaining); ++ u8 *p = (u8 *)((uintptr_t)ioparam->src + offset); ++ u8 *q = (u8 *)ioparam->dst + offset; ++ ++ rc = dma_memcpy(vcdma, bus_addr, ++ INTALIAS_L1L2_NONALLOCATING((u32)(uintptr_t)p), ++ (s + dma_xfer_chunk - 1) & ~(dma_xfer_chunk - 1)); ++ if (rc) { ++ dev_err(vcdma->dev, "dma_memcpy failed\n"); ++ break; ++ } ++ if (copy_to_user(q, buf, s) != 0) { ++ pr_err("%s: copy_to_user failed\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ } ++ ++out: ++ if (buf) ++ dma_free_coherent(vcdma->dev, PAGE_ALIGN(size), buf, ++ bus_addr); ++ ++ mutex_unlock(&dma_mutex); ++ ++ return rc; ++} ++ + static long + vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +@@ -163,6 +386,21 @@ vc_mem_ioctl(struct file *file, unsigned + } + break; + } ++ case VC_MEM_IOC_DMACOPY: ++ { ++ struct vc_mem_dmacopy ioparam; ++ /* Get the parameter data. ++ */ ++ if (copy_from_user ++ (&ioparam, (void *)arg, sizeof(ioparam))) { ++ pr_err("%s: copy_from_user failed\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ ++ rc = vc_mem_copy(&ioparam); ++ break; ++ } + default: + { + return -ENOTTY; +@@ -193,6 +431,24 @@ vc_mem_compat_ioctl(struct file *file, u + + break; + ++ case VC_MEM_IOC_DMACOPY32: ++ { ++ struct vc_mem_dmacopy32 param32; ++ struct vc_mem_dmacopy param; ++ /* Get the parameter data. ++ */ ++ if (copy_from_user(¶m32, (void *)arg, sizeof(param32))) { ++ pr_err("%s: copy_from_user failed\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ param.dst = compat_ptr(param32.dst); ++ param.src = param32.src; ++ param.length = param32.length; ++ rc = vc_mem_copy(¶m); ++ break; ++ } ++ + default: + rc = vc_mem_ioctl(file, cmd, arg); + break; +@@ -330,6 +586,7 @@ vc_mem_init(void) + vc_mem_debugfs_init(dev); + #endif + ++ mutex_init(&dma_mutex); + vc_mem_inited = 1; + return 0; + +@@ -352,6 +609,7 @@ vc_mem_exit(void) + { + pr_debug("%s: called\n", __func__); + ++ vc_mem_dma_uninit(); + if (vc_mem_inited) { + #ifdef CONFIG_DEBUG_FS + vc_mem_debugfs_deinit(); +@@ -360,6 +618,7 @@ vc_mem_exit(void) + class_destroy(vc_mem_class); + cdev_del(&vc_mem_cdev); + unregister_chrdev_region(vc_mem_devnum, 1); ++ vc_mem_inited = 0; + } + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1032-drm-vc4-Correct-address-offset-for-planes-with-src_-.patch b/target/linux/bcm27xx/patches-6.1/950-1032-drm-vc4-Correct-address-offset-for-planes-with-src_-.patch new file mode 100644 index 0000000000..32112f949b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1032-drm-vc4-Correct-address-offset-for-planes-with-src_-.patch @@ -0,0 +1,48 @@ +From 6ab30a5dd3fb2ccbd918f147e91eb9bfe9849970 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 16 Oct 2023 12:13:38 +0100 +Subject: [PATCH] drm/vc4: Correct address offset for planes with src_[xy] + offsets + +11cf37e741b4 switched to using drm_fb_dma_get_gem_addr instead of +drm_fb_dma_get_gem_obj and adding fb->offset[]. + +However the tiled formats need to compute the offset in a more +involved manner than drm_fb_dma_get_gem_addr applies, and we +were ending up with the offset for src_[xy] being applied twice. + +Switch back to using drm_fb_dma_get_gem_obj and fully computing +the offsets ourselves. + +Fixes: 11cf37e741b4 ("drm/vc4: Move the buffer offset out of the vc4_plane_state") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1447,9 +1447,9 @@ static int vc4_plane_mode_set(struct drm + vc4_state->ptr0_offset[0] = vc4_state->dlist_count; + + for (i = 0; i < num_planes; i++) { +- dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); ++ struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, i); + +- vc4_dlist_write(vc4_state, paddr + offsets[i]); ++ vc4_dlist_write(vc4_state, bo->dma_addr + fb->offsets[i] + offsets[i]); + } + + /* Pointer Context Word 0/1/2: Written by the HVS */ +@@ -1842,9 +1842,8 @@ static int vc6_plane_mode_set(struct drm + * TODO: This only covers Raster Scan Order planes + */ + for (i = 0; i < num_planes; i++) { +- dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); +- +- paddr += offsets[i]; ++ struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, i); ++ dma_addr_t paddr = bo->dma_addr + fb->offsets[i] + offsets[i]; + + /* Pointer Word 0 */ + vc4_state->ptr0_offset[i] = vc4_state->dlist_count; diff --git a/target/linux/bcm27xx/patches-6.1/950-1033-drivers-media-rp1_cfe-Fix-link-validate-test-for-pix.patch b/target/linux/bcm27xx/patches-6.1/950-1033-drivers-media-rp1_cfe-Fix-link-validate-test-for-pix.patch new file mode 100644 index 0000000000..3e1d504da0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1033-drivers-media-rp1_cfe-Fix-link-validate-test-for-pix.patch @@ -0,0 +1,69 @@ +From c14550658832026e82111f2a89b3f7bf567afc1c Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 17 Oct 2023 09:35:44 +0100 +Subject: [PATCH] drivers: media: rp1_cfe: Fix link validate test for pixel + format + +Now that we have removed unique PISP media bus codes, the cfe format +table has multiple entries with the same media bus code for 16-bit +formats. The test in cfe_video_link_validate() did not account for this. +Fix it by testing the media bus code and the V4L2 pixelformat 4cc +together. + +As a drive-by, ensure we have a valid CSI2 datatype id when programming +the hardware block. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -786,6 +786,9 @@ static void cfe_start_channel(struct cfe + width = source_fmt->width; + height = source_fmt->height; + ++ /* Must have a valid CSI2 datatype. */ ++ WARN_ON(!fmt->csi_dt); ++ + /* + * Start the associated CSI2 Channel as well. + * +@@ -809,6 +812,9 @@ static void cfe_start_channel(struct cfe + node_desc[node->id].link_pad - CSI2_NUM_CHANNELS); + fmt = find_format_by_code(source_fmt->code); + ++ /* Must have a valid CSI2 datatype. */ ++ WARN_ON(!fmt->csi_dt); ++ + if (is_image_output_node(node)) { + width = source_fmt->width; + height = source_fmt->height; +@@ -1504,7 +1510,8 @@ static int cfe_video_link_validate(struc + + if (is_image_output_node(node)) { + struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix; +- const struct cfe_fmt *fmt; ++ const struct cfe_fmt *fmt = NULL; ++ unsigned int i; + + if (source_fmt->width != pix_fmt->width || + source_fmt->height != pix_fmt->height) { +@@ -1516,8 +1523,14 @@ static int cfe_video_link_validate(struc + goto out; + } + +- fmt = find_format_by_code(source_fmt->code); +- if (!fmt || fmt->fourcc != pix_fmt->pixelformat) { ++ for (i = 0; i < ARRAY_SIZE(formats); i++) { ++ if (formats[i].code == source_fmt->code && ++ formats[i].fourcc == pix_fmt->pixelformat) { ++ fmt = &formats[i]; ++ break; ++ } ++ } ++ if (!fmt) { + cfe_err("Format mismatch!\n"); + ret = -EINVAL; + goto out; diff --git a/target/linux/bcm27xx/patches-6.1/950-1034-dts-bcm2712-Use-the-new-model-name.patch b/target/linux/bcm27xx/patches-6.1/950-1034-dts-bcm2712-Use-the-new-model-name.patch new file mode 100644 index 0000000000..f30456835a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1034-dts-bcm2712-Use-the-new-model-name.patch @@ -0,0 +1,23 @@ +From b6bfece0d9ddf21e1526fead81340ef02f98f6ad Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 17 Oct 2023 17:28:11 +0100 +Subject: [PATCH] dts: bcm2712: Use the new model name + +"Model B" is no more - "Raspberry Pi 5" is the official name. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -52,7 +52,7 @@ + + / { + compatible = "raspberrypi,5-model-b", "brcm,bcm2712"; +- model = "Raspberry Pi 5 Model B"; ++ model = "Raspberry Pi 5"; + + /* Will be filled by the bootloader */ + memory@0 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1035-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch b/target/linux/bcm27xx/patches-6.1/950-1035-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch new file mode 100644 index 0000000000..df87a1b757 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1035-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch @@ -0,0 +1,93 @@ +From 0c7fb448e0e0e47c2b3be64e438208682c6a5e61 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 9 Oct 2023 16:32:45 +0100 +Subject: [PATCH] fbdev: Allow client to request a particular /dev/fbN node + +Add a flag custom_fb_num to denote that the client has +requested a specific fbdev node number via node. + +Signed-off-by: Dave Stevenson +--- + drivers/video/fbdev/core/fbmem.c | 24 +++++++++++++++++------- + include/linux/fb.h | 2 ++ + 2 files changed, 19 insertions(+), 7 deletions(-) + +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -52,6 +52,7 @@ static DEFINE_MUTEX(registration_lock); + + struct fb_info *registered_fb[FB_MAX] __read_mostly; + int num_registered_fb __read_mostly; ++int min_dynamic_fb __read_mostly; + #define for_each_registered_fb(i) \ + for (i = 0; i < FB_MAX; i++) \ + if (!registered_fb[i]) {} else +@@ -1579,19 +1580,22 @@ static int do_register_framebuffer(struc + return -ENXIO; + + num_registered_fb++; +- for (i = 0 ; i < FB_MAX; i++) +- if (!registered_fb[i]) +- break; +- fb_info->node = i; ++ if (!fb_info->custom_fb_num || fb_info->node >= FB_MAX || registered_fb[fb_info->node]) { ++ for (i = min_dynamic_fb ; i < FB_MAX; i++) ++ if (!registered_fb[i]) ++ break; ++ fb_info->node = i; ++ } + refcount_set(&fb_info->count, 1); + mutex_init(&fb_info->lock); + mutex_init(&fb_info->mm_lock); + + fb_info->dev = device_create(fb_class, fb_info->device, +- MKDEV(FB_MAJOR, i), NULL, "fb%d", i); ++ MKDEV(FB_MAJOR, fb_info->node), NULL, "fb%d", fb_info->node); + if (IS_ERR(fb_info->dev)) { + /* Not fatal */ +- printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); ++ printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", ++ fb_info->node, PTR_ERR(fb_info->dev)); + fb_info->dev = NULL; + } else + fb_init_device(fb_info); +@@ -1624,7 +1628,7 @@ static int do_register_framebuffer(struc + + fb_var_to_videomode(&mode, &fb_info->var); + fb_add_videomode(&mode, &fb_info->modelist); +- registered_fb[i] = fb_info; ++ registered_fb[fb_info->node] = fb_info; + + #ifdef CONFIG_GUMSTIX_AM200EPD + { +@@ -1719,6 +1723,12 @@ static int fb_aperture_acquire_for_platf + return ret; + } + ++void fb_set_lowest_dynamic_fb(int min_fb_dev) ++{ ++ min_dynamic_fb = min_fb_dev; ++} ++EXPORT_SYMBOL(fb_set_lowest_dynamic_fb); ++ + /** + * register_framebuffer - registers a frame buffer device + * @fb_info: frame buffer info structure +--- a/include/linux/fb.h ++++ b/include/linux/fb.h +@@ -512,6 +512,7 @@ struct fb_info { + } *apertures; + + bool skip_vt_switch; /* no VT switch on suspend/resume required */ ++ bool custom_fb_num; /* Use value in node as the preferred node number */ + }; + + static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { +@@ -614,6 +615,7 @@ extern ssize_t fb_sys_write(struct fb_in + size_t count, loff_t *ppos); + + /* drivers/video/fbmem.c */ ++extern void fb_set_lowest_dynamic_fb(int min_fb_dev); + extern int register_framebuffer(struct fb_info *fb_info); + extern void unregister_framebuffer(struct fb_info *fb_info); + extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); diff --git a/target/linux/bcm27xx/patches-6.1/950-1036-drm-fb-helper-Look-up-preferred-fbdev-node-number-fr.patch b/target/linux/bcm27xx/patches-6.1/950-1036-drm-fb-helper-Look-up-preferred-fbdev-node-number-fr.patch new file mode 100644 index 0000000000..3e360be77b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1036-drm-fb-helper-Look-up-preferred-fbdev-node-number-fr.patch @@ -0,0 +1,41 @@ +From 1216ea56c2e30aee4975b4dcce79ebd199afaf8f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 9 Oct 2023 16:34:36 +0100 +Subject: [PATCH] drm/fb-helper: Look up preferred fbdev node number from DT + +For situations where there are multiple DRM cards in a system, +add a query of DT for "drm_fb" designations for cards to set +their preferred /dev/fbN designation. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_fb_helper.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -1932,7 +1932,7 @@ __drm_fb_helper_initial_config_and_unloc + struct drm_device *dev = fb_helper->dev; + struct fb_info *info; + unsigned int width, height; +- int ret; ++ int ret, id; + + width = dev->mode_config.max_width; + height = dev->mode_config.max_height; +@@ -1967,6 +1967,15 @@ __drm_fb_helper_initial_config_and_unloc + * register the fbdev emulation instance in kernel_fb_helper_list. */ + mutex_unlock(&fb_helper->lock); + ++ id = of_alias_get_highest_id("drm_fb"); ++ if (id >= 0) ++ fb_set_lowest_dynamic_fb(id + 1); ++ ++ id = of_alias_get_id(dev->dev->of_node, "drm_fb"); ++ if (id >= 0) { ++ info->node = id; ++ info->custom_fb_num = true; ++ } + ret = register_framebuffer(info); + if (ret < 0) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-1037-dt-Add-overrides-for-drm-framebuffer-allocations-on-.patch b/target/linux/bcm27xx/patches-6.1/950-1037-dt-Add-overrides-for-drm-framebuffer-allocations-on-.patch new file mode 100644 index 0000000000..924c1b9f19 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1037-dt-Add-overrides-for-drm-framebuffer-allocations-on-.patch @@ -0,0 +1,72 @@ +From 61b138adaeaddefe749f421a3b69c67d4a49a8e3 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 11 Oct 2023 11:03:51 +0100 +Subject: [PATCH] dt: Add overrides for drm framebuffer allocations on Pi5 + +Adds dtparam overrides to the base Pi5 DT such that vc4, +DSI0, DSI1, or DPI can be requested to be /dev/fb[012]. +No override is specified by default, so the order will be +based on probe order (aka semi-random). Any device that +doesn't have an override specified will be placed above +all specified overrides. Having an fb1 or fb2 override but +no fb0 one will result in no console via fbcon. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 12 ++++++++++++ + arch/arm/boot/dts/overlays/README | 24 ++++++++++++++++++++++++ + 2 files changed, 36 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -824,5 +824,17 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + act_led_trigger = <&act_led>, "linux,default-trigger"; + pwr_led_activelow = <&pwr_led>, "gpios:8"; + pwr_led_trigger = <&pwr_led>, "linux,default-trigger"; ++ 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; + }; + }; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -173,6 +173,30 @@ Params: + cooling_fan Enables the Pi 5 cooling fan (enabled + automatically by the firmware) + ++ drm_fb0_rp1_dpi Assign /dev/fb0 to the RP1 DPI output ++ ++ drm_fb0_rp1_dsi0 Assign /dev/fb0 to the RP1 DSI0 output ++ ++ drm_fb0_rp1_dsi1 Assign /dev/fb0 to the RP1 DSI1 output ++ ++ drm_fb0_vc4 Assign /dev/fb0 to the vc4 outputs ++ ++ drm_fb1_rp1_dpi Assign /dev/fb1 to the RP1 DPI output ++ ++ drm_fb1_rp1_dsi0 Assign /dev/fb1 to the RP1 DSI0 output ++ ++ drm_fb1_rp1_dsi1 Assign /dev/fb1 to the RP1 DSI1 output ++ ++ drm_fb1_vc4 Assign /dev/fb1 to the vc4 outputs ++ ++ drm_fb2_rp1_dpi Assign /dev/fb2 to the RP1 DPI output ++ ++ drm_fb2_rp1_dsi0 Assign /dev/fb2 to the RP1 DSI0 output ++ ++ drm_fb2_rp1_dsi1 Assign /dev/fb2 to the RP1 DSI1 output ++ ++ drm_fb2_vc4 Assign /dev/fb2 to the vc4 outputs ++ + eee Enable Energy Efficient Ethernet support for + compatible devices (default "on"). See also + "tx_lpi_timer". Pi3B+ only. diff --git a/target/linux/bcm27xx/patches-6.1/950-1039-drm-connector-Change-DRM-card-alias-from-underscore-.patch b/target/linux/bcm27xx/patches-6.1/950-1039-drm-connector-Change-DRM-card-alias-from-underscore-.patch new file mode 100644 index 0000000000..57782d51c3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1039-drm-connector-Change-DRM-card-alias-from-underscore-.patch @@ -0,0 +1,26 @@ +From f429fc1a072d4bb35e622a1012a5a52914eba4e3 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:34:58 +0100 +Subject: [PATCH] drm/connector: Change DRM card alias from underscore to + hyphen + +Apparently aliases are only allowed lower case and hyphens, +so swap the use of underscore to hyphen. + +Fixes: 3aa1f2477545 ("drm: Look for an alias for the displays to use as the DRM device name") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_connector.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -112,7 +112,7 @@ static struct drm_conn_prop_enum_list dr + }; + + #define MAX_DT_NODE_NAME_LEN 20 +-#define DT_DRM_NODE_PREFIX "drm_" ++#define DT_DRM_NODE_PREFIX "drm-" + + static void drm_connector_get_of_name(int type, char *node_name, int length) + { diff --git a/target/linux/bcm27xx/patches-6.1/950-1040-dt-Alter-alias-names-from-_-to-for-drm_dsiN.patch b/target/linux/bcm27xx/patches-6.1/950-1040-dt-Alter-alias-names-from-_-to-for-drm_dsiN.patch new file mode 100644 index 0000000000..0536924d05 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1040-dt-Alter-alias-names-from-_-to-for-drm_dsiN.patch @@ -0,0 +1,24 @@ +From e33170e21494279801e9f17eeb910ec45ebd740c Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:28:43 +0100 +Subject: [PATCH] dt: Alter alias names from _ to - for drm_dsiN + +Fixes: 7ec42740a45b ("dt: Add DSI1 and DSI2 aliases to 2712") +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -787,8 +787,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + gpio4 = &pinctrl_aon; + usb0 = &rp1_usb0; + usb1 = &rp1_usb1; +- drm_dsi1 = &dsi0; +- drm_dsi2 = &dsi1; ++ drm-dsi1 = &dsi0; ++ drm-dsi2 = &dsi1; + }; + + __overrides__ { diff --git a/target/linux/bcm27xx/patches-6.1/950-1041-drm-fb_helper-Change-query-for-FB-designation-from-d.patch b/target/linux/bcm27xx/patches-6.1/950-1041-drm-fb_helper-Change-query-for-FB-designation-from-d.patch new file mode 100644 index 0000000000..78e5b89be4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1041-drm-fb_helper-Change-query-for-FB-designation-from-d.patch @@ -0,0 +1,28 @@ +From 0e9e925112fabdbd448e17947796317a6dbca96e Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:32:04 +0100 +Subject: [PATCH] drm/fb_helper: Change query for FB designation from drm_fb to + drm-fb + +Fixes: 1216ea56c2e3 ("drm/fb-helper: Look up preferred fbdev node number from DT") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_fb_helper.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -1967,11 +1967,11 @@ __drm_fb_helper_initial_config_and_unloc + * register the fbdev emulation instance in kernel_fb_helper_list. */ + mutex_unlock(&fb_helper->lock); + +- id = of_alias_get_highest_id("drm_fb"); ++ id = of_alias_get_highest_id("drm-fb"); + if (id >= 0) + fb_set_lowest_dynamic_fb(id + 1); + +- id = of_alias_get_id(dev->dev->of_node, "drm_fb"); ++ id = of_alias_get_id(dev->dev->of_node, "drm-fb"); + if (id >= 0) { + info->node = id; + info->custom_fb_num = true; diff --git a/target/linux/bcm27xx/patches-6.1/950-1042-dt-Alter-alias-names-from-_-to-for-drm_fbN_-override.patch b/target/linux/bcm27xx/patches-6.1/950-1042-dt-Alter-alias-names-from-_-to-for-drm_fbN_-override.patch new file mode 100644 index 0000000000..42865dc7ff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1042-dt-Alter-alias-names-from-_-to-for-drm_fbN_-override.patch @@ -0,0 +1,43 @@ +From 87be94059193d0bc64d52a9535df4fb1891c72fe Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:29:20 +0100 +Subject: [PATCH] dt: Alter alias names from _ to - for drm_fbN_* overrides + +Fixes: 61b138adaead ("dt: Add overrides for drm framebuffer allocations on Pi5") +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -824,17 +824,17 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + act_led_trigger = <&act_led>, "linux,default-trigger"; + pwr_led_activelow = <&pwr_led>, "gpios:8"; + pwr_led_trigger = <&pwr_led>, "linux,default-trigger"; +- 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; ++ 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; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1044-Typo-in-overlays-README.patch b/target/linux/bcm27xx/patches-6.1/950-1044-Typo-in-overlays-README.patch new file mode 100644 index 0000000000..19720e8645 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1044-Typo-in-overlays-README.patch @@ -0,0 +1,21 @@ +From cb8a4adb586c5e926e415ac0dae3ffb4af30b0a9 Mon Sep 17 00:00:00 2001 +From: Andrew Scheller +Date: Thu, 19 Oct 2023 14:13:36 +0100 +Subject: [PATCH] Typo in overlays README + +touchscreen-size-y for rpi-ft5406 defaults to 480, not 600 +--- + arch/arm/boot/dts/overlays/README | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3738,7 +3738,7 @@ Name: rpi-ft5406 + Info: Official Raspberry Pi display touchscreen + Load: dtoverlay=rpi-ft5406,= + Params: touchscreen-size-x Touchscreen X resolution (default 800) +- touchscreen-size-y Touchscreen Y resolution (default 600); ++ touchscreen-size-y Touchscreen Y resolution (default 480); + touchscreen-inverted-x Invert touchscreen X coordinates (default 0); + touchscreen-inverted-y Invert touchscreen Y coordinates (default 0); + touchscreen-swapped-x-y Swap X and Y cordinates (default 0); diff --git a/target/linux/bcm27xx/patches-6.1/950-1045-dts-bcm2712-Add-the-krnbt-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-1045-dts-bcm2712-Add-the-krnbt-parameter.patch new file mode 100644 index 0000000000..95940dd830 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1045-dts-bcm2712-Add-the-krnbt-parameter.patch @@ -0,0 +1,23 @@ +From 4cb97982f88d8fb623ace5a9511198e442e993ba Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 20 Oct 2023 17:15:25 +0100 +Subject: [PATCH] dts: bcm2712: Add the krnbt parameter + +Add a Pi 5 implementation of the krnbt parameter, for symmetry and +for tinkering purposes. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -809,6 +809,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + 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"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1047-drm-vc4_fkms-Fix-up-interrupt-handler-for-both-2835-.patch b/target/linux/bcm27xx/patches-6.1/950-1047-drm-vc4_fkms-Fix-up-interrupt-handler-for-both-2835-.patch new file mode 100644 index 0000000000..99b8426e1c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1047-drm-vc4_fkms-Fix-up-interrupt-handler-for-both-2835-.patch @@ -0,0 +1,109 @@ +From 4137b49989ce710305e476d0bd1086d7d906ff50 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 20 Oct 2023 17:09:54 +0100 +Subject: [PATCH] drm/vc4_fkms: Fix up interrupt handler for both 2835/2711 and + 2712 + +2712 has switched from using the SMI peripheral to another interrupt +source for the vsync interrupt, so handle both sources cleanly. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++++------ + 1 file changed, 38 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -47,9 +47,15 @@ struct get_display_cfg { + u32 max_pixel_clock[2]; //Max pixel clock for each display + }; + ++enum vc4_fkms_revision { ++ BCM2835_6_7, ++ BCM2711, ++ BCM2712, ++}; ++ + struct vc4_fkms { + struct get_display_cfg cfg; +- bool bcm2711; ++ enum vc4_fkms_revision revision; + }; + + #define PLANES_PER_CRTC 8 +@@ -1149,7 +1155,7 @@ vc4_crtc_mode_valid(struct drm_crtc *crt + /* Pi4 can't generate odd horizontal timings on HDMI, so reject modes + * that would set them. + */ +- if (fkms->bcm2711 && ++ if (fkms->revision >= BCM2711 && + (vc4_crtc->display_number == 2 || vc4_crtc->display_number == 7) && + !(mode->flags & DRM_MODE_FLAG_DBLCLK) && + ((mode->hdisplay | /* active */ +@@ -1267,6 +1273,20 @@ static irqreturn_t vc4_crtc_irq_handler( + return ret; + } + ++static irqreturn_t vc4_crtc2712_irq_handler(int irq, void *data) ++{ ++ struct vc4_crtc **crtc_list = data; ++ int i; ++ ++ for (i = 0; crtc_list[i]; i++) { ++ if (crtc_list[i]->vblank_enabled) ++ drm_crtc_handle_vblank(&crtc_list[i]->base); ++ vc4_crtc_handle_page_flip(crtc_list[i]); ++ } ++ ++ return IRQ_HANDLED; ++} ++ + static int vc4_fkms_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, +@@ -1352,9 +1372,12 @@ static const struct drm_crtc_helper_func + }; + + static const struct of_device_id vc4_firmware_kms_dt_match[] = { +- { .compatible = "raspberrypi,rpi-firmware-kms" }, ++ { .compatible = "raspberrypi,rpi-firmware-kms", ++ .data = (void *)BCM2835_6_7 }, + { .compatible = "raspberrypi,rpi-firmware-kms-2711", +- .data = (void *)1 }, ++ .data = (void *)BCM2711 }, ++ { .compatible = "raspberrypi,rpi-firmware-kms-2712", ++ .data = (void *)BCM2712 }, + {} + }; + +@@ -1924,8 +1947,7 @@ static int vc4_fkms_bind(struct device * + match = of_match_device(vc4_firmware_kms_dt_match, dev); + if (!match) + return -ENODEV; +- if (match->data) +- fkms->bcm2711 = true; ++ fkms->revision = (enum vc4_fkms_revision)match->data; + + firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0); + vc4->firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node); +@@ -1992,10 +2014,16 @@ static int vc4_fkms_bind(struct device * + if (IS_ERR(crtc_list[0]->regs)) + DRM_ERROR("Oh dear, failed to map registers\n"); + +- writel(0, crtc_list[0]->regs + SMICS); +- ret = devm_request_irq(dev, platform_get_irq(pdev, 0), +- vc4_crtc_irq_handler, 0, +- "vc4 firmware kms", crtc_list); ++ if (fkms->revision >= BCM2712) { ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_crtc2712_irq_handler, 0, ++ "vc4 firmware kms", crtc_list); ++ } else { ++ writel(0, crtc_list[0]->regs + SMICS); ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_crtc_irq_handler, 0, ++ "vc4 firmware kms", crtc_list); ++ } + if (ret) + DRM_ERROR("Oh dear, failed to register IRQ\n"); + } else { diff --git a/target/linux/bcm27xx/patches-6.1/950-1048-dt-Switch-bcm2712-firmware-kms-node-to-using-the-271.patch b/target/linux/bcm27xx/patches-6.1/950-1048-dt-Switch-bcm2712-firmware-kms-node-to-using-the-271.patch new file mode 100644 index 0000000000..9dea2d0fff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1048-dt-Switch-bcm2712-firmware-kms-node-to-using-the-271.patch @@ -0,0 +1,25 @@ +From 5a52cae54a05499a8487f392cf5dfc3d8a837e6f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 20 Oct 2023 17:12:09 +0100 +Subject: [PATCH] dt: Switch bcm2712 firmware-kms node to using the 2712 + compatible + +With the new compatible to handle the interrupts correctly, switch +the base dt to use it. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -103,7 +103,7 @@ + }; + + firmwarekms: firmwarekms@7d503000 { +- compatible = "raspberrypi,rpi-firmware-kms"; ++ compatible = "raspberrypi,rpi-firmware-kms-2712"; + /* SUN_L2 interrupt reg */ + reg = <0x7d503000 0x18>; + interrupt-parent = <&cpu_l2_irq>; diff --git a/target/linux/bcm27xx/patches-6.1/950-1049-drivers-media-imx477-Disable-the-scaler.patch b/target/linux/bcm27xx/patches-6.1/950-1049-drivers-media-imx477-Disable-the-scaler.patch new file mode 100644 index 0000000000..841fa42440 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1049-drivers-media-imx477-Disable-the-scaler.patch @@ -0,0 +1,35 @@ +From f075893e9b0e241879998c0b12cf8af0ba7737da Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 23 Oct 2023 10:03:03 +0100 +Subject: [PATCH] drivers: media: imx477: Disable the scaler + +The horizontal scaler was enabled for the 2028x1520 and 2028x1080 modes, +with a scale factor of 1. It caused a single column of bad pixels on the +right edge of the image. Since scaling is not needed for these modes, +disable it entirely. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx477.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -632,7 +632,7 @@ static const struct imx477_reg mode_2028 + {0x9e9f, 0x00}, + {0xa2a9, 0x60}, + {0xa2b7, 0x00}, +- {0x0401, 0x01}, ++ {0x0401, 0x00}, + {0x0404, 0x00}, + {0x0405, 0x20}, + {0x0408, 0x00}, +@@ -733,7 +733,7 @@ static const struct imx477_reg mode_2028 + {0x9e9f, 0x00}, + {0xa2a9, 0x60}, + {0xa2b7, 0x00}, +- {0x0401, 0x01}, ++ {0x0401, 0x00}, + {0x0404, 0x00}, + {0x0405, 0x20}, + {0x0408, 0x00}, diff --git a/target/linux/bcm27xx/patches-6.1/950-1050-dt-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch b/target/linux/bcm27xx/patches-6.1/950-1050-dt-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch new file mode 100644 index 0000000000..77f30a345d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1050-dt-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch @@ -0,0 +1,37 @@ +From eccaa8588fca9c9ec950664f1d5894bd826b57b0 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 23 Oct 2023 14:10:15 +0100 +Subject: [PATCH] dt: Add drm_fbN_vc4 overrides for Pi0-4 + +Follows up '61b138adaead ("dt: Add overrides for drm framebuffer +allocations on Pi5")' with an equivalent for Pi0-4. + +These will have no effect on most normal systems, but drm_fb0_vc4 +will stop SPI displays jumping in and claiming /dev/fb0. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm270x-rpi.dtsi | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm270x-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm270x-rpi.dtsi +@@ -1,7 +1,7 @@ + /* Downstream modifications to bcm2835-rpi.dtsi */ + + / { +- aliases { ++ aliases: aliases { + aux = &aux; + sound = &sound; + soc = &soc; +@@ -98,6 +98,9 @@ + sdio_overclock = <&mmc>,"brcm,overclock-50:0", + <&mmcnr>,"brcm,overclock-50:0"; + axiperf = <&axiperf>,"status"; ++ drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; ++ drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; ++ drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1051-fixup-overlays-mcp23017-allow-specification-of-the-i.patch b/target/linux/bcm27xx/patches-6.1/950-1051-fixup-overlays-mcp23017-allow-specification-of-the-i.patch new file mode 100644 index 0000000000..5016e78778 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1051-fixup-overlays-mcp23017-allow-specification-of-the-i.patch @@ -0,0 +1,95 @@ +From 3ed6d34d53e94ecbebc64c8fa3d1b6d3c41db8fb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 24 Oct 2023 09:58:52 +0100 +Subject: [PATCH] fixup! overlays: mcp23017: allow specification of the i2c bus + +The incorrect fragment order (*) caused broke the interrupt usage, and +while it was being fixed the lack of a reference to the pinctrl +declaration was noticed. + +See: https://github.com/raspberrypi/linux/issues/5677 + +Signed-off-by: Phil Elwell + +(*) Ideally all fragments would appear in the file in the order in which +they should be merged, but that is easy to forget and can be awkward, so +the firmware merges all "intra" fragments (those that target other +fragments in the overlay) before "inter" fragments (those that target +the base DTB). However, intra fragments that target other intra +fragments is a level of nesting too far for this logic to cope, so they +must appear before the fragments they target. +--- + .../boot/dts/overlays/mcp23017-overlay.dts | 42 ++++++++++--------- + 1 file changed, 22 insertions(+), 20 deletions(-) + +--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts +@@ -24,30 +24,13 @@ + }; + + fragment@2 { +- target = <&i2cbus>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- +- mcp23017: mcp@20 { +- compatible = "microchip,mcp23017"; +- reg = <0x20>; +- gpio-controller; +- #gpio-cells = <2>; +- +- status = "okay"; +- }; +- }; +- }; +- +- fragment@3 { + target = <&mcp23017>; + __dormant__ { + compatible = "microchip,mcp23008"; + }; + }; + +- fragment@4 { ++ fragment@3 { + target = <&mcp23017>; + mcp23017_irq: __overlay__ { + #interrupt-cells=<2>; +@@ -58,6 +41,25 @@ + }; + }; + ++ fragment@4 { ++ target = <&i2cbus>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp23017: mcp@20 { ++ compatible = "microchip,mcp23017"; ++ pinctrl-name = "default"; ++ pinctrl-0 = <&mcp23017_pins>; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ status = "okay"; ++ }; ++ }; ++ }; ++ + frag100: fragment@100 { + target = <&i2c1>; + i2cbus: __overlay__ { +@@ -83,8 +85,8 @@ + gpiopin = <&mcp23017_pins>,"brcm,pins:0", + <&mcp23017_irq>,"interrupts:0"; + addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0"; +- mcp23008 = <0>,"=3"; +- noints = <0>,"!1!4"; ++ mcp23008 = <0>,"=2"; ++ noints = <0>,"!1!3"; + i2c0 = <&frag100>, "target:0=",<&i2c0>; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1052-drivers-media-pisp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch b/target/linux/bcm27xx/patches-6.1/950-1052-drivers-media-pisp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch new file mode 100644 index 0000000000..7fe0c50740 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1052-drivers-media-pisp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch @@ -0,0 +1,54 @@ +From 8d53cc5b4b2a6f9baed7a0aa801a39ad9dce9bf8 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 26 Oct 2023 08:55:24 +0100 +Subject: [PATCH] drivers: media: pisp_be: Add back V4L2_PIX_FMT_RPI_BE format + +Add the opaque V4L2_PIX_FMT_RPI_BE format back to the format list as it +is needed for the verification test suite. Also set the default format +to YUV420 non-multiplanar. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/pisp_be/pisp_be.c | 9 ++++++--- + .../media/platform/raspberrypi/pisp_be/pisp_be_formats.h | 5 +++++ + 2 files changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +@@ -1230,8 +1230,11 @@ static int try_format(struct v4l2_format + return verify_be_pix_format(f, node); + + fmt = find_format(pixfmt); +- if (!fmt) +- fmt = find_format(V4L2_PIX_FMT_YUV420M); ++ if (!fmt) { ++ dev_dbg(pispbe->dev, "%s: [%s] Format not found, defaulting to YUV420\n", ++ __func__, NODE_NAME(node)); ++ fmt = find_format(V4L2_PIX_FMT_YUV420); ++ } + + f->fmt.pix_mp.pixelformat = fmt->fourcc; + f->fmt.pix_mp.num_planes = fmt->num_planes; +@@ -1576,7 +1579,7 @@ static void node_set_default_format(stru + } else { + struct v4l2_format f = {0}; + +- f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; ++ 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; +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +@@ -457,6 +457,11 @@ 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.1/950-1053-dt-bindings-PCI-brcmstb-add-optional-property-brcm-t.patch b/target/linux/bcm27xx/patches-6.1/950-1053-dt-bindings-PCI-brcmstb-add-optional-property-brcm-t.patch new file mode 100644 index 0000000000..3ef42e7967 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1053-dt-bindings-PCI-brcmstb-add-optional-property-brcm-t.patch @@ -0,0 +1,32 @@ +From f1154884295a4bd00d6ebcaf01fa30141145903d Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 20 Sep 2023 10:04:15 +0100 +Subject: [PATCH] dt-bindings: PCI: brcmstb: add optional property - + "brcm,tperst-clk-ms" + +This property can be used to delay deassertion of external fundamental +reset, which may be useful for endpoints that require an extended time for +internal setup to complete. + +Signed-off-by: Jonathan Bell +--- + Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml +@@ -77,6 +77,14 @@ properties: + minItems: 1 + maxItems: 3 + ++ brcm,tperst-clk-ms: ++ category: optional ++ type: int ++ description: u32 giving the number of milliseconds to extend ++ the time between internal release of fundamental reset and ++ the deassertion of the external PERST# pin. This has the ++ effect of increasing the Tperst_clk phase of link init. ++ + required: + - compatible + - reg diff --git a/target/linux/bcm27xx/patches-6.1/950-1054-drivers-pci-brcmstb-optionally-extend-Tperst_clk-tim.patch b/target/linux/bcm27xx/patches-6.1/950-1054-drivers-pci-brcmstb-optionally-extend-Tperst_clk-tim.patch new file mode 100644 index 0000000000..021e210591 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1054-drivers-pci-brcmstb-optionally-extend-Tperst_clk-tim.patch @@ -0,0 +1,71 @@ +From 4b0c6453808a662869a43c504913f3b7ed64486a Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 20 Sep 2023 13:01:11 +0100 +Subject: [PATCH] drivers: pci: brcmstb: optionally extend Tperst_clk time + during link-up + +The RC has a feature that allows for manual control over the deassertion +of the PERST# output pin, which allows the time between refclk active +and reset deassert at the EP to be increased. + +Signed-off-by: Jonathan Bell +--- + drivers/pci/controller/pcie-brcmstb.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -138,6 +138,7 @@ + + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG pcie->reg_offsets[PCIE_HARD_DEBUG] + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2 ++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK 0x8 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000 + #define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK 0x00200000 +@@ -352,6 +353,7 @@ struct brcm_pcie { + bool (*rc_mode)(struct brcm_pcie *pcie); + struct subdev_regulators *sr; + bool ep_wakeup_capable; ++ u32 tperst_clk_ms; + }; + + static inline bool is_bmips(const struct brcm_pcie *pcie) +@@ -1388,9 +1390,28 @@ static int brcm_pcie_start_link(struct b + u16 nlw, cls, lnksta; + bool ssc_good = false; + int ret, i; ++ u32 tmp; + + /* Unassert the fundamental reset */ +- pcie->perst_set(pcie, 0); ++ if (pcie->tperst_clk_ms) { ++ /* ++ * Increase Tperst_clk time by forcing PERST# output low while ++ * the internal reset is released, so the PLL generates stable ++ * refclk output further in advance of PERST# deassertion. ++ */ ++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK); ++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ ++ pcie->perst_set(pcie, 0); ++ msleep(pcie->tperst_clk_ms); ++ ++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ u32p_replace_bits(&tmp, 0, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK); ++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ } else { ++ pcie->perst_set(pcie, 0); ++ } + + /* + * Wait for 100ms after PERST# deassertion; see PCIe CEM specification +@@ -1923,6 +1944,7 @@ static int brcm_pcie_probe(struct platfo + pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc"); + pcie->l1ss = of_property_read_bool(np, "brcm,enable-l1ss"); + pcie->rcb_mps_mode = of_property_read_bool(np, "brcm,enable-mps-rcb"); ++ of_property_read_u32(np, "brcm,tperst-clk-ms", &pcie->tperst_clk_ms); + + ret = clk_prepare_enable(pcie->clk); + if (ret) { diff --git a/target/linux/bcm27xx/patches-6.1/950-1055-arm-dt-add-dtparams-for-PCIe-reset-timing-override.patch b/target/linux/bcm27xx/patches-6.1/950-1055-arm-dt-add-dtparams-for-PCIe-reset-timing-override.patch new file mode 100644 index 0000000000..a81d0383ac --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1055-arm-dt-add-dtparams-for-PCIe-reset-timing-override.patch @@ -0,0 +1,59 @@ +From db90a5e5fc2fbd843b29eb8110ed5e03604a2887 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 20 Sep 2023 13:04:54 +0100 +Subject: [PATCH] arm: dt: add dtparams for PCIe reset timing override + +The Pi 5 variant gets two parameters so that the CM4-compatible +name will also work on Pi 5. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 2 ++ + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + arch/arm/boot/dts/overlays/README | 7 +++++++ + 3 files changed, 11 insertions(+) + +--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts +@@ -446,5 +446,7 @@ i2c_csi_dsi0: &i2c0 { + 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/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -814,6 +814,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + 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_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; + spi = <&spi0>, "status"; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -280,6 +280,10 @@ Params: + (2711 only, but not applicable on CM4S) + N.B. USB-A ports on 4B are subsequently disabled + ++ pcie_tperst_clk_ms Add N milliseconds between PCIe reference clock ++ activation and PERST# deassertion ++ (CM4 and 2712, default "0") ++ + pciex1 Set to "on" to enable the external PCIe link + (2712 only, default "off") + +@@ -290,6 +294,9 @@ Params: + PCIe link for devices that have broken + implementations (2712 only, default "off") + ++ pciex1_tperst_clk_ms Alias for pcie_tperst_clk_ms ++ (2712 only, default "0") ++ + spi Set to "on" to enable the spi interfaces + (default "off") + diff --git a/target/linux/bcm27xx/patches-6.1/950-1056-arm-dt-bcm2712-don-t-unconditionally-enable-MPS-read.patch b/target/linux/bcm27xx/patches-6.1/950-1056-arm-dt-bcm2712-don-t-unconditionally-enable-MPS-read.patch new file mode 100644 index 0000000000..b08a5720d5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1056-arm-dt-bcm2712-don-t-unconditionally-enable-MPS-read.patch @@ -0,0 +1,35 @@ +From cb013b6602de32c647ed08faf899596664a18635 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Thu, 26 Oct 2023 13:47:54 +0100 +Subject: [PATCH] arm: dt: bcm2712: don't unconditionally enable MPS read + completions + +RP1 supports it, but it's not a given that an arbitrary EP device +on PCIE2 will. Migrate the property to the rp1_target fragment. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 1 + + arch/arm/boot/dts/bcm2712.dtsi | 1 - + 2 files changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -160,6 +160,7 @@ + }; + + rp1_target: &pcie2 { ++ brcm,enable-mps-rcb; + brcm,vdm-qos-map = <0xbbaa9888>; + aspm-no-l0s; + status = "okay"; +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -1086,7 +1086,6 @@ + 0x00 0x00000000 + 0x10 0x00000000>; + +- brcm,enable-mps-rcb; + brcm,enable-l1ss; + status = "disabled"; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1057-drivers-media-imx477-Set-horizontal-binning-when-dis.patch b/target/linux/bcm27xx/patches-6.1/950-1057-drivers-media-imx477-Set-horizontal-binning-when-dis.patch new file mode 100644 index 0000000000..e6122e1a6b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1057-drivers-media-imx477-Set-horizontal-binning-when-dis.patch @@ -0,0 +1,39 @@ +From 8dcc16f0adc50f5cb8a11a6dde238131d0ca45a0 Mon Sep 17 00:00:00 2001 +From: David Plowman +Date: Fri, 27 Oct 2023 12:14:22 +0100 +Subject: [PATCH] drivers: media: imx477: Set horizontal binning when disabling + the scaler + +The horizontal scaler has been disabled but actually the sensor is not +binning horizontally, resulting in images that are stretched 2x +horizontally (missing the right half of the field of view completely). + +Therefore we must additionally set the horizontal binning mode. There +is only marginal change in output quality and noise levels. + +Signed-off-by: David Plowman +Fixes: f075893e9b0e ("drivers: media: imx477: Disable the scaler") +--- + drivers/media/i2c/imx477.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -607,7 +607,7 @@ static const struct imx477_reg mode_2028 + {0x0385, 0x01}, + {0x0387, 0x01}, + {0x0900, 0x01}, +- {0x0901, 0x12}, ++ {0x0901, 0x22}, + {0x0902, 0x02}, + {0x3140, 0x02}, + {0x3c00, 0x00}, +@@ -708,7 +708,7 @@ static const struct imx477_reg mode_2028 + {0x0385, 0x01}, + {0x0387, 0x01}, + {0x0900, 0x01}, +- {0x0901, 0x12}, ++ {0x0901, 0x22}, + {0x0902, 0x02}, + {0x3140, 0x02}, + {0x3c00, 0x00}, diff --git a/target/linux/bcm27xx/patches-6.1/950-1058-fixup-arch-arm64-Add-Revision-Serial-Model-to-cpuinf.patch b/target/linux/bcm27xx/patches-6.1/950-1058-fixup-arch-arm64-Add-Revision-Serial-Model-to-cpuinf.patch new file mode 100644 index 0000000000..adedaf6d4b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1058-fixup-arch-arm64-Add-Revision-Serial-Model-to-cpuinf.patch @@ -0,0 +1,25 @@ +From e641fd7a50987ad6b7ce1ab36189bc8817295e42 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 31 Oct 2023 16:34:56 +0000 +Subject: [PATCH] fixup! arch/arm64: Add Revision, Serial, Model to cpuinfo + +Delete the Hardware string, which is pointless and misleading. + +See: https://github.com/raspberrypi/bookworm-feedback/issues/129 + +Signed-off-by: Phil Elwell +--- + arch/arm64/kernel/cpuinfo.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/arch/arm64/kernel/cpuinfo.c ++++ b/arch/arm64/kernel/cpuinfo.c +@@ -224,8 +224,6 @@ static int c_show(struct seq_file *m, vo + seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr)); + } + +- seq_printf(m, "Hardware\t: BCM2835\n"); +- + np = of_find_node_by_path("/system"); + if (np) { + if (!of_property_read_u32(np, "linux,revision", &revision)) diff --git a/target/linux/bcm27xx/patches-6.1/950-1060-dts-bcm2710-rpi-zero-2-w-Remove-WLAN-firmwares.patch b/target/linux/bcm27xx/patches-6.1/950-1060-dts-bcm2710-rpi-zero-2-w-Remove-WLAN-firmwares.patch new file mode 100644 index 0000000000..18c12cd10f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1060-dts-bcm2710-rpi-zero-2-w-Remove-WLAN-firmwares.patch @@ -0,0 +1,35 @@ +From e86c43b86179fba90a1d9dd5acb554767af6740f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 12 Jun 2023 15:23:55 +0100 +Subject: [PATCH] dts: bcm2710-rpi-zero-2-w: Remove WLAN firmwares + +With careful use of qualified firmware names there is no need for the +ability to override the device names based on Device Tree properties. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts | 13 ------------- + 1 file changed, 13 deletions(-) + +--- a/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts +@@ -161,19 +161,6 @@ + brcmf: wifi@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; +- +- firmwares { +- fw_43436p { +- chipid = <43430>; +- revmask = <4>; +- fw_base = "brcm/brcmfmac43436-sdio"; +- }; +- fw_43436s { +- chipid = <43430>; +- revmask = <2>; +- fw_base = "brcm/brcmfmac43436s-sdio"; +- }; +- }; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1061-drivers-media-cfe-Set-the-CSI-2-link-frequency-corre.patch b/target/linux/bcm27xx/patches-6.1/950-1061-drivers-media-cfe-Set-the-CSI-2-link-frequency-corre.patch new file mode 100644 index 0000000000..d5aeae5333 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1061-drivers-media-cfe-Set-the-CSI-2-link-frequency-corre.patch @@ -0,0 +1,111 @@ +From a11312709f46b71bf320a9dcc8cf4e09056552cd Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 1 Nov 2023 13:25:54 +0000 +Subject: [PATCH] drivers: media: cfe: Set the CSI-2 link frequency correctly + +Use the sensor provided link frequency to set the DPHY timing parameters +on stream_on. This replaces the hard-coded 999 MHz value currently being +used. As a fallback, revert to the original 999 Mhz link frequency. + +As a drive-by, fix a 80-character line formatting error. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 63 +++++++++++++++++-- + 1 file changed, 58 insertions(+), 5 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -780,7 +780,8 @@ static void cfe_start_channel(struct cfe + __func__, node_desc[FE_OUT0].name, + cfe->fe_csi2_channel); + +- source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, cfe->fe_csi2_channel); ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, ++ cfe->fe_csi2_channel); + fmt = find_format_by_code(source_fmt->code); + + width = source_fmt->width; +@@ -982,6 +983,59 @@ static void cfe_buffer_queue(struct vb2_ + spin_unlock_irqrestore(&cfe->state_lock, flags); + } + ++static u64 sensor_link_frequency(struct cfe_device *cfe) ++{ ++ struct v4l2_mbus_framefmt *source_fmt; ++ struct v4l2_subdev_state *state; ++ struct media_entity *entity; ++ struct v4l2_subdev *subdev; ++ const struct cfe_fmt *fmt; ++ struct media_pad *pad; ++ s64 link_freq; ++ ++ state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd); ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, 0); ++ fmt = find_format_by_code(source_fmt->code); ++ v4l2_subdev_unlock_state(state); ++ ++ /* ++ * Walk up the media graph to find either the sensor entity, or another ++ * entity that advertises the V4L2_CID_LINK_FREQ or V4L2_CID_PIXEL_RATE ++ * control through the subdev. ++ */ ++ entity = &cfe->csi2.sd.entity; ++ while (1) { ++ pad = &entity->pads[0]; ++ if (!(pad->flags & MEDIA_PAD_FL_SINK)) ++ goto err; ++ ++ pad = media_pad_remote_pad_first(pad); ++ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) ++ goto err; ++ ++ entity = pad->entity; ++ subdev = media_entity_to_v4l2_subdev(entity); ++ if (entity->function == MEDIA_ENT_F_CAM_SENSOR || ++ v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_LINK_FREQ) || ++ v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_PIXEL_RATE)) ++ break; ++ } ++ ++ link_freq = v4l2_get_link_freq(subdev->ctrl_handler, fmt->depth, ++ cfe->csi2.active_data_lanes * 2); ++ if (link_freq < 0) ++ goto err; ++ ++ /* x2 for DDR. */ ++ link_freq *= 2; ++ cfe_info("Using a link frequency of %lld Hz\n", link_freq); ++ return link_freq; ++ ++err: ++ cfe_err("Unable to determine sensor link frequency, using 999 MHz\n"); ++ return 999 * 1000000UL; ++} ++ + static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count) + { + struct v4l2_mbus_config mbus_config = { 0 }; +@@ -1049,10 +1103,11 @@ static int cfe_start_streaming(struct vb + goto err_disable_cfe; + } + +- cfe_dbg("Starting sensor streaming\n"); +- ++ cfe_dbg("Configuring CSI-2 block\n"); ++ cfe->csi2.dphy.dphy_freq = sensor_link_frequency(cfe) / 1000000UL; + csi2_open_rx(&cfe->csi2); + ++ cfe_dbg("Starting sensor streaming\n"); + cfe->sequence = 0; + ret = v4l2_subdev_call(cfe->sensor, video, s_stream, 1); + if (ret < 0) { +@@ -1945,8 +2000,6 @@ static int of_cfe_connect_subdevs(struct + } + } + +- /* TODO: Get the frequency from devicetree */ +- cfe->csi2.dphy.dphy_freq = 999; + cfe->csi2.dphy.num_lanes = ep.bus.mipi_csi2.num_data_lanes; + cfe->csi2.bus_flags = ep.bus.mipi_csi2.flags; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1062-dts-bcm2712-rpi-5-b-Create-some-dummy-nodes.patch b/target/linux/bcm27xx/patches-6.1/950-1062-dts-bcm2712-rpi-5-b-Create-some-dummy-nodes.patch new file mode 100644 index 0000000000..722714d56a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1062-dts-bcm2712-rpi-5-b-Create-some-dummy-nodes.patch @@ -0,0 +1,42 @@ +From fb78b2617e70e58e03e0d50e674758fdd2a80d45 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Nov 2023 10:39:11 +0000 +Subject: [PATCH] dts: bcm2712-rpi-5-b: Create some dummy nodes + +The kernel now treats multiple fragments targeting the same node as an +error. For this reason, it is important that labels created just for +compatibility with other systems (e.g. i2c0if and i2c0mux) are +attached to unique nodes, not just tacked onto existing nodes. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -157,6 +157,12 @@ + dummy: dummy { + // A target for unwanted overlay fragments + }; ++ ++ ++ // A few extra labels to keep overlays happy ++ ++ i2c0if: i2c0if {}; ++ i2c0mux: i2c0mux {}; + }; + + rp1_target: &pcie2 { +@@ -243,11 +249,6 @@ aux: &dummy {}; + + #include "bcm2712-rpi.dtsi" + +-// A few extra labels to keep overlays happy +- +-i2c0if: &rp1_gpio {}; +-i2c0mux: &rp1_gpio {}; +- + i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only + pinctrl-0 = <&rp1_i2c6_38_39>; + pinctrl-names = "default"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1063-dts-rp1-Add-spi6-fix-spi1-address-cells.patch b/target/linux/bcm27xx/patches-6.1/950-1063-dts-rp1-Add-spi6-fix-spi1-address-cells.patch new file mode 100644 index 0000000000..41ab025555 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1063-dts-rp1-Add-spi6-fix-spi1-address-cells.patch @@ -0,0 +1,49 @@ +From cd66a0832351762b496bdce6f2f94a871d11484e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Nov 2023 13:12:55 +0000 +Subject: [PATCH] dts: rp1: Add spi6, fix spi1 #address-cells + +spi6 won't be useful on Pi 5 because it can't be enabled on the 40-pin +header, but include it for completeness. + +Also fix the #address-cells value for spi1, otherwise the kernel will +reject attempts to apply the, say, spi1-2cs overlay at runtime. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/rp1.dtsi | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/rp1.dtsi ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -187,7 +187,7 @@ + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; + clock-names = "ssi_clk"; +- #address-cells = <0>; ++ #address-cells = <1>; + #size-cells = <0>; + num-cs = <2>; + dmas = <&rp1_dma RP1_DMA_SPI1_TX>, +@@ -262,6 +262,21 @@ + 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 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1064-overlays-uart-n-pi5-Add-the-pinctrl-0-property.patch b/target/linux/bcm27xx/patches-6.1/950-1064-overlays-uart-n-pi5-Add-the-pinctrl-0-property.patch new file mode 100644 index 0000000000..b6e0c323db --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1064-overlays-uart-n-pi5-Add-the-pinctrl-0-property.patch @@ -0,0 +1,67 @@ +From 17f135b742c4edb340afb365873c3a574f7e16cb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Nov 2023 17:05:46 +0000 +Subject: [PATCH] overlays: uart-pi5: Add the pinctrl-0 property + +Without the pinctrl-0 property in the overlays, the UARTs may not be +mapped correctly. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts | 1 + + 5 files changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart0>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart0_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart1>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart1_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart2>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart2_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart3>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart3_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart4>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart4_pins>; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1065-drivers-media-imx477-Add-V4L2_CID_LINK_FREQ-control.patch b/target/linux/bcm27xx/patches-6.1/950-1065-drivers-media-imx477-Add-V4L2_CID_LINK_FREQ-control.patch new file mode 100644 index 0000000000..f0a652b520 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1065-drivers-media-imx477-Add-V4L2_CID_LINK_FREQ-control.patch @@ -0,0 +1,51 @@ +From c9a785d57c302d5f1d4de4e67fa57522e66c7882 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 6 Nov 2023 09:40:50 +0000 +Subject: [PATCH] drivers: media: imx477: Add V4L2_CID_LINK_FREQ control + +Add V4L2_CID_LINK_FREQ as a read-only control with a value of 450 Mhz. +This will be used by the CFE driver to corretly setup the DPHY timing +parameters in the CSI-2 block. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx477.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -164,6 +164,10 @@ struct imx477_mode { + struct imx477_reg_list reg_list; + }; + ++static const s64 imx477_link_freq_menu[] = { ++ IMX477_DEFAULT_LINK_FREQ, ++}; ++ + static const struct imx477_reg mode_common_regs[] = { + {0x0136, 0x18}, + {0x0137, 0x00}, +@@ -1110,6 +1114,7 @@ struct imx477 { + struct v4l2_ctrl_handler ctrl_handler; + /* V4L2 Controls */ + struct v4l2_ctrl *pixel_rate; ++ struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *hflip; +@@ -1997,6 +2002,15 @@ static int imx477_init_controls(struct i + IMX477_PIXEL_RATE, 1, + IMX477_PIXEL_RATE); + ++ /* LINK_FREQ is also read only */ ++ imx477->link_freq = ++ v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ ARRAY_SIZE(imx477_link_freq_menu) - 1, 0, ++ imx477_link_freq_menu); ++ if (imx477->link_freq) ++ imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ + /* + * Create the controls here, but mode specific limits are setup + * in the imx477_set_framing_limits() call below. diff --git a/target/linux/bcm27xx/patches-6.1/950-1066-drivers-media-imx477-Correctly-set-IMX477_PIXEL_RATE.patch b/target/linux/bcm27xx/patches-6.1/950-1066-drivers-media-imx477-Correctly-set-IMX477_PIXEL_RATE.patch new file mode 100644 index 0000000000..f62fbbe13d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1066-drivers-media-imx477-Correctly-set-IMX477_PIXEL_RATE.patch @@ -0,0 +1,24 @@ +From 46913ee0590ee0e3f607ab189be19a4d0ce785f2 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 6 Nov 2023 09:42:37 +0000 +Subject: [PATCH] drivers: media: imx477: Correctly set IMX477_PIXEL_RATE as a + r/o control + +This control is meant to be read-only, mark it as such. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx477.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -2001,6 +2001,8 @@ static int imx477_init_controls(struct i + IMX477_PIXEL_RATE, + IMX477_PIXEL_RATE, 1, + IMX477_PIXEL_RATE); ++ if (imx477->pixel_rate) ++ imx477->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* LINK_FREQ is also read only */ + imx477->link_freq = diff --git a/target/linux/bcm27xx/patches-6.1/950-1067-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch b/target/linux/bcm27xx/patches-6.1/950-1067-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch new file mode 100644 index 0000000000..948d79bfdb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1067-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch @@ -0,0 +1,52 @@ +From 6e9f68bba01b9c36a77b68c4b3167c317da986da Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 26 Oct 2023 17:46:13 +0100 +Subject: [PATCH] drm/vc4: Correct logic on stopping an HVS channel + +When factoring out __vc4_hvs_stop_channel, the logic got inverted from + if (condition) + // stop channel +to + if (condition) + goto out + //stop channel + out: +and also changed the exact register writes used to stop the channel. + +Correct the logic so that the channel is actually stopped, and revert +to the original register writes. + +Fixes: 6d01a106b4c8 ("drm/vc4: crtc: Move HVS init and close to a function") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -992,13 +992,11 @@ static void __vc4_hvs_stop_channel(struc + if (!drm_dev_enter(drm, &idx)) + return; + +- if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE) ++ if (!(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)) + goto out; + +- HVS_WRITE(SCALER_DISPCTRLX(chan), +- HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET); +- HVS_WRITE(SCALER_DISPCTRLX(chan), +- HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE); ++ HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET); ++ HVS_WRITE(SCALER_DISPCTRLX(chan), 0); + + /* Once we leave, the scaler should be disabled and its fifo empty. */ + WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET); +@@ -1026,7 +1024,7 @@ static void __vc6_hvs_stop_channel(struc + if (!drm_dev_enter(drm, &idx)) + return; + +- if (HVS_READ(SCALER6_DISPX_CTRL0(chan)) & SCALER6_DISPX_CTRL0_ENB) ++ if (!(HVS_READ(SCALER6_DISPX_CTRL0(chan)) & SCALER6_DISPX_CTRL0_ENB)) + goto out; + + HVS_WRITE(SCALER6_DISPX_CTRL0(chan), diff --git a/target/linux/bcm27xx/patches-6.1/950-1068-drm-vc4-Drop-WARN-for-HVS-FIFOs-not-being-empty.patch b/target/linux/bcm27xx/patches-6.1/950-1068-drm-vc4-Drop-WARN-for-HVS-FIFOs-not-being-empty.patch new file mode 100644 index 0000000000..627f22c845 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1068-drm-vc4-Drop-WARN-for-HVS-FIFOs-not-being-empty.patch @@ -0,0 +1,30 @@ +From 31c4c359aa2dbb1a7c095f0a6ef4e13cd46cfd14 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 26 Oct 2023 18:05:09 +0100 +Subject: [PATCH] drm/vc4: Drop WARN for HVS FIFOs not being empty + +The reset condition for the EMPTY flag in DISPSTATx is 0, +so seeing as we've just reset the pipeline there is no +guarantee that the flag will denote empty if it hasn't been +enabled. + +Drop the WARN. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1005,10 +1005,6 @@ static void __vc4_hvs_stop_channel(struc + SCALER_DISPSTATX_MODE) != + SCALER_DISPSTATX_MODE_DISABLED); + +- WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) & +- (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != +- SCALER_DISPSTATX_EMPTY); +- + out: + drm_dev_exit(idx); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-1069-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch b/target/linux/bcm27xx/patches-6.1/950-1069-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch new file mode 100644 index 0000000000..ce03224c39 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1069-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch @@ -0,0 +1,85 @@ +From 8b7078d1bbd8bb548cc97d5214adb828e9f0037c Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 26 Oct 2023 18:23:31 +0100 +Subject: [PATCH] drm/vc4: Free all stale dlists if channel is disabled + +The code handling freeing stale dlists had 2 issues: +- it disabled the interrupt as soon as the first EOF interrupt + occurred, even if it didn't clear all stale allocations, thus + leading to stale entries +- It didn't free stale entries from disabled channels, so eg + "kmstest -c 0" could leave a stale alloc on channel 1 floating + around. + +Keep the interrupt enabled whilst there are any outstanding +allocs, and discard those on disabled channels. This second +channel does require us to call vc4_hvs_stop_channel from +vc4_crtc_atomic_disable so that the channel actually gets stopped. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++ + drivers/gpu/drm/vc4/vc4_hvs.c | 27 +++++++++++++++++++++++++-- + 2 files changed, 27 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -660,6 +660,8 @@ static void vc4_crtc_atomic_disable(stru + + vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel); + ++ vc4_hvs_atomic_disable(crtc, state); ++ + /* + * Make sure we issue a vblank event after disabling the CRTC if + * someone was waiting it. +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -697,7 +697,8 @@ static void vc4_hvs_schedule_dlist_sweep + if (!list_empty(&hvs->stale_dlist_entries)) + queue_work(system_unbound_wq, &hvs->free_dlist_work); + +- vc4_hvs_irq_clear_eof(hvs, channel); ++ if (list_empty(&hvs->stale_dlist_entries)) ++ vc4_hvs_irq_clear_eof(hvs, channel); + + spin_unlock_irqrestore(&hvs->mm_lock, flags); + } +@@ -712,6 +713,27 @@ static bool vc4_hvs_frcnt_lte(u8 cnt1, u + return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0; + } + ++bool vc4_hvs_check_channel_active(struct vc4_hvs *hvs, unsigned int fifo) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; ++ bool enabled = false; ++ int idx; ++ ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ ++ if (!drm_dev_enter(drm, &idx)) ++ return 0; ++ ++ if (vc4->gen >= VC4_GEN_6) ++ enabled = HVS_READ(SCALER6_DISPX_CTRL0(fifo)) & SCALER6_DISPX_CTRL0_ENB; ++ else ++ enabled = HVS_READ(SCALER_DISPCTRLX(fifo)) & SCALER_DISPCTRLX_ENABLE; ++ ++ drm_dev_exit(idx); ++ return enabled; ++} ++ + /* + * Some atomic commits (legacy cursor updates, mostly) will not wait for + * the next vblank and will just return once the commit has been pushed +@@ -746,7 +768,8 @@ static void vc4_hvs_dlist_free_work(stru + u8 frcnt; + + frcnt = vc4_hvs_get_fifo_frame_count(hvs, cur->channel); +- if (!vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt)) ++ if (vc4_hvs_check_channel_active(hvs, cur->channel) && ++ !vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt)) + continue; + + vc4_hvs_free_dlist_entry_locked(hvs, cur); diff --git a/target/linux/bcm27xx/patches-6.1/950-1070-drm-vc4-Add-hvs_dlist_allocs-debugfs-function.patch b/target/linux/bcm27xx/patches-6.1/950-1070-drm-vc4-Add-hvs_dlist_allocs-debugfs-function.patch new file mode 100644 index 0000000000..b16489a12d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1070-drm-vc4-Add-hvs_dlist_allocs-debugfs-function.patch @@ -0,0 +1,64 @@ +From 665e9810340abc37769b317445907bac1843dd64 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 27 Oct 2023 16:46:04 +0100 +Subject: [PATCH] drm/vc4: Add hvs_dlist_allocs debugfs function. + +Users are reporting running out of DLIST memory. Add a +debugfs file to dump out all the allocations. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -347,6 +347,36 @@ static int vc5_hvs_debugfs_gamma(struct + return 0; + } + ++static int vc4_hvs_debugfs_dlist_allocs(struct seq_file *m, void *data) ++{ ++ struct drm_info_node *node = m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct drm_printer p = drm_seq_file_printer(m); ++ struct vc4_hvs_dlist_allocation *cur, *next; ++ struct drm_mm_node *mm_node; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&hvs->mm_lock, flags); ++ ++ drm_printf(&p, "Allocated nodes:\n"); ++ list_for_each_entry(mm_node, drm_mm_nodes(&hvs->dlist_mm), node_list) { ++ drm_printf(&p, "node [%08llx + %08llx]\n", mm_node->start, mm_node->size); ++ } ++ ++ drm_printf(&p, "Stale nodes:\n"); ++ list_for_each_entry_safe(cur, next, &hvs->stale_dlist_entries, node) { ++ drm_printf(&p, "node [%08llx + %08llx] channel %u frcnt %u\n", ++ cur->mm_node.start, cur->mm_node.size, cur->channel, ++ cur->target_frame_count); ++ } ++ ++ spin_unlock_irqrestore(&hvs->mm_lock, flags); ++ ++ return 0; ++} ++ + /* The filter kernel is composed of dwords each containing 3 9-bit + * signed integers packed next to each other. + */ +@@ -1602,6 +1632,11 @@ int vc4_hvs_debugfs_init(struct drm_mino + if (ret) + return ret; + ++ ret = vc4_debugfs_add_file(minor, "hvs_dlist_allocs", ++ vc4_hvs_debugfs_dlist_allocs, NULL); ++ if (ret) ++ return ret; ++ + ret = vc4_debugfs_add_regset32(minor, "hvs_regs", + &hvs->regset); + if (ret) diff --git a/target/linux/bcm27xx/patches-6.1/950-1071-drm-vc4-Log-the-size-of-the-dlist-allocation-that-wa.patch b/target/linux/bcm27xx/patches-6.1/950-1071-drm-vc4-Log-the-size-of-the-dlist-allocation-that-wa.patch new file mode 100644 index 0000000000..aa38b182ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1071-drm-vc4-Log-the-size-of-the-dlist-allocation-that-wa.patch @@ -0,0 +1,23 @@ +From 23ea21ef5f6efb3082c184843b35a2f8f2e4374c Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 31 Oct 2023 11:15:38 +0000 +Subject: [PATCH] drm/vc4: Log the size of the dlist allocation that was + attempted + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -659,7 +659,8 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs + dlist_count); + spin_unlock_irqrestore(&hvs->mm_lock, flags); + if (ret) { +- drm_err(dev, "Failed to allocate DLIST entry: %d\n", ret); ++ drm_err(dev, "Failed to allocate DLIST entry. Requested size=%zu. ret=%d\n", ++ dlist_count, ret); + return ERR_PTR(ret); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1072-drm-vc4-crtc-Support-odd-horizontal-timings-on-BCM27.patch b/target/linux/bcm27xx/patches-6.1/950-1072-drm-vc4-crtc-Support-odd-horizontal-timings-on-BCM27.patch new file mode 100644 index 0000000000..a72e3b8e5b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1072-drm-vc4-crtc-Support-odd-horizontal-timings-on-BCM27.patch @@ -0,0 +1,104 @@ +From f9f480b04f1dc280bd4411477f5ee7336361367b Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 24 Oct 2023 16:20:42 +0100 +Subject: [PATCH] drm/vc4: crtc: Support odd horizontal timings on BCM2712 + +BCM2711 runs pixelvalve at two pixels per clock cycle which results +in an unfortunate limitation that odd horizontal timings are not +possible. This is apparent on the standard DMT mode of 1366x768@60 +which cannot be driven with correct timing. + +BCM2712 defaults to the same behaviour, but has a mode to support +odd timings. While internally it still runs at two pixels per clock, +setting the PV_VCONTROL_ODD_TIMING bit makes it appear externally +to behave as it is one pixel per clock. + +Switching to this mode fixes 1366x768@60 mode, and other custom +resultions with odd horizontal timings. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 12 ++++-------- + drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_regs.h | 1 + + 3 files changed, 7 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -398,12 +398,6 @@ static void vc4_crtc_config_pv(struct dr + + vc4_crtc_pixelvalve_reset(crtc); + +- /* +- * NOTE: The BCM2712 has a H_OTE (Horizontal Odd Timing Enable) +- * bit that, when set, will allow to specify the timings in +- * pixels instead of cycles, thus allowing to specify odd +- * timings. +- */ + CRTC_WRITE(PV_HORZA, + VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc, + PV_HORZA_HBP) | +@@ -448,6 +442,7 @@ 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) | + (is_dsi ? PV_VCONTROL_DSI : 0) | + PV_VCONTROL_INTERLACE | + (odd_field_first +@@ -459,6 +454,7 @@ 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) | + (is_dsi ? PV_VCONTROL_DSI : 0)); + CRTC_WRITE(PV_VSYNCD_EVEN, 0); + } +@@ -1334,7 +1330,7 @@ const struct vc4_pv_data bcm2712_pv0_dat + .hvs_output = 0, + }, + .fifo_depth = 64, +- .pixels_per_clock = 2, ++ .pixels_per_clock = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI0, + }, +@@ -1347,7 +1343,7 @@ const struct vc4_pv_data bcm2712_pv1_dat + .hvs_output = 1, + }, + .fifo_depth = 64, +- .pixels_per_clock = 2, ++ .pixels_per_clock = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI1, + }, +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -3958,7 +3958,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_2, + PHY_LANE_CK, + }, +- .unsupported_odd_h_timings = true, ++ .unsupported_odd_h_timings = false, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +@@ -3985,7 +3985,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_2, + PHY_LANE_CK, + }, +- .unsupported_odd_h_timings = true, ++ .unsupported_odd_h_timings = false, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -155,6 +155,7 @@ + # define PV_CONTROL_EN BIT(0) + + #define PV_V_CONTROL 0x04 ++# define PV_VCONTROL_ODD_TIMING BIT(29) + # define PV_VCONTROL_ODD_DELAY_MASK VC4_MASK(22, 6) + # define PV_VCONTROL_ODD_DELAY_SHIFT 6 + # define PV_VCONTROL_ODD_FIRST BIT(5) diff --git a/target/linux/bcm27xx/patches-6.1/950-1073-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch b/target/linux/bcm27xx/patches-6.1/950-1073-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch new file mode 100644 index 0000000000..caf8b1a462 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1073-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch @@ -0,0 +1,41 @@ +From 686fe776309fba5cad642c40177d39bf1fb320b2 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 7 Nov 2023 14:49:47 +0000 +Subject: [PATCH] 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 +@@ -275,8 +275,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); + } +@@ -602,6 +604,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.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch b/target/linux/bcm27xx/patches-6.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch new file mode 100644 index 0000000000..2ab224df05 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch @@ -0,0 +1,62 @@ +From 4d2261fe86ce08bbee3c000718000e9f86593d88 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 11:52:16 +0000 +Subject: [PATCH] drivers: mmc: sdhci: add SPURIOUS_INT_RESP quirk + +Certain controllers (dwc-mshc) generate timeout conditions separately to +command-completion conditions, where the end result is interrupts are +separated in time depending on the current SDCLK frequency. + +This causes spurious interrupts if SDCLK is slow compared to the CPU's +ability to process and return from interrupt. This occurs during card +probe with an empty slot where all commands that would generate a +response time out. + +Add a quirk to squelch command response interrupts when a command +timeout interrupt is received. + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/host/sdhci.c | 11 +++++++++++ + drivers/mmc/host/sdhci.h | 3 +++ + 2 files changed, 14 insertions(+) + +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -1728,6 +1728,12 @@ static bool sdhci_send_command(struct sd + if (host->use_external_dma) + sdhci_external_dma_pre_transfer(host, cmd); + ++ if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { ++ host->ier |= SDHCI_INT_RESPONSE; ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ } ++ + sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); + + return true; +@@ -3330,6 +3336,11 @@ static void sdhci_cmd_irq(struct sdhci_h + if (intmask & SDHCI_INT_TIMEOUT) { + host->cmd->error = -ETIMEDOUT; + sdhci_err_stats_inc(host, CMD_TIMEOUT); ++ if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { ++ host->ier &= ~SDHCI_INT_RESPONSE; ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ } + } else { + host->cmd->error = -EILSEQ; + if (!mmc_op_tuning(host->cmd->opcode)) +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -486,6 +486,9 @@ struct sdhci_host { + #define SDHCI_QUIRK2_NO_SDR50 (1<<20) + #define SDHCI_QUIRK2_NO_SDR104 (1<<21) + ++/* Command timeouts may generate a trailing INT_RESPONSE later */ ++#define SDHCI_QUIRK2_SPURIOUS_INT_RESP (1<<31) ++ + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ + phys_addr_t mapbase; /* physical address base */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1076-dt-bindings-mmc-sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch b/target/linux/bcm27xx/patches-6.1/950-1076-dt-bindings-mmc-sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch new file mode 100644 index 0000000000..ffdc1b1c5d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1076-dt-bindings-mmc-sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch @@ -0,0 +1,42 @@ +From ebe13d0d4314255d226ba740e37a14172a8b9091 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 16:10:13 +0000 +Subject: [PATCH] dt-bindings: mmc: sdhci-of-dwcmhsc: Add Raspberry Pi RP1 + support + +The DWC MSHC controller on RP1 needs differentiating from the generic +version. + +Signed-off-by: Jonathan Bell +--- + .../devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml ++++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml +@@ -16,6 +16,7 @@ allOf: + properties: + compatible: + enum: ++ - raspberrypi,rp1-dwcmshc + - rockchip,rk3568-dwcmshc + - rockchip,rk3588-dwcmshc + - snps,dwcmshc-sdhci +@@ -34,6 +35,8 @@ properties: + - description: axi clock for rockchip specified + - description: block clock for rockchip specified + - description: timer clock for rockchip specified ++ - description: timeout clock for rp1 specified ++ - description: sdio clock generator for rp1 specified + + + clock-names: +@@ -44,6 +47,8 @@ properties: + - const: axi + - const: block + - const: timer ++ - const: timeout ++ - const: sdio + + rockchip,txclk-tapnum: + description: Specify the number of delay for tx sampling. diff --git a/target/linux/bcm27xx/patches-6.1/950-1077-drivers-mmc-sdhci-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch b/target/linux/bcm27xx/patches-6.1/950-1077-drivers-mmc-sdhci-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch new file mode 100644 index 0000000000..54b719c6ec --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1077-drivers-mmc-sdhci-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch @@ -0,0 +1,41 @@ +From 80dd8795ca631ac692fd3079487aea6d934a829c Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 16:12:59 +0000 +Subject: [PATCH] drivers: mmc: sdhci-of-dwcmshc: add RP1 dt ID and quirks + +Differentiate the RP1 variant of the Designware MSHC controller(s). + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -373,6 +373,15 @@ static const struct sdhci_pltfm_data sdh + }; + #endif + ++static const struct sdhci_pltfm_data sdhci_dwcmshc_rp1_pdata = { ++ .ops = &sdhci_dwcmshc_ops, ++ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | ++ SDHCI_QUIRK_BROKEN_CARD_DETECTION, ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | ++ SDHCI_QUIRK2_BROKEN_HS200 | ++ SDHCI_QUIRK2_SPURIOUS_INT_RESP, ++}; ++ + static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { + .ops = &sdhci_dwcmshc_rk35xx_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | +@@ -441,6 +450,10 @@ static void dwcmshc_rk35xx_postinit(stru + + static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { + { ++ .compatible = "raspberrypi,rp1-dwcmshc", ++ .data = &sdhci_dwcmshc_rp1_pdata, ++ }, ++ { + .compatible = "rockchip,rk3588-dwcmshc", + .data = &sdhci_dwcmshc_rk35xx_pdata, + }, diff --git a/target/linux/bcm27xx/patches-6.1/950-1078-arm-dts-change-RP1-SDHCI-controller-compatible-strin.patch b/target/linux/bcm27xx/patches-6.1/950-1078-arm-dts-change-RP1-SDHCI-controller-compatible-strin.patch new file mode 100644 index 0000000000..c708bf1f71 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1078-arm-dts-change-RP1-SDHCI-controller-compatible-strin.patch @@ -0,0 +1,104 @@ +From 51cdff455e3c3df29764f71bc0c9dd0e099945d6 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 16:14:25 +0000 +Subject: [PATCH] arm: dts: change RP1 SDHCI controller compatible string + +Also add a sdio-pi5 overlay which enables mmc0 on GPIOs 22-27, as was +possible with earlier models of Pi. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 7 ++++++ + arch/arm/boot/dts/overlays/overlay_map.dts | 4 ++++ + .../boot/dts/overlays/sdio-pi5-overlay.dts | 24 +++++++++++++++++++ + arch/arm/boot/dts/rp1.dtsi | 4 ++-- + 5 files changed, 38 insertions(+), 2 deletions(-) + create mode 100644 arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -225,6 +225,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + sc16is752-spi1.dtbo \ + sdhost.dtbo \ + sdio.dtbo \ ++ sdio-pi5.dtbo \ + seeed-can-fd-hat-v1.dtbo \ + seeed-can-fd-hat-v2.dtbo \ + sh1106-spi.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3932,6 +3932,13 @@ Info: This overlay is now deprecated. + Load: + + ++Name: sdio-pi5 ++Info: Selects the rp1_mmc0 interface and enables it on GPIOs 22-27. ++ Pi 5 only. ++Load: dtoverlay=sdio-pi5 ++Params: ++ ++ + Name: sdtweak + Info: This overlay is now deprecated. Use the sd_* dtparams in the + base DTB, e.g. "dtoverlay=sdtweak,poll_once" becomes +--- a/arch/arm/boot/dts/overlays/overlay_map.dts ++++ b/arch/arm/boot/dts/overlays/overlay_map.dts +@@ -250,6 +250,10 @@ + deprecated = "use sdio,bus_width=1,gpios_22_25"; + }; + ++ sdio-pi5 { ++ bcm2712; ++ }; ++ + sdtweak { + deprecated = "use 'dtparam=sd_poll_once' etc."; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts +@@ -0,0 +1,24 @@ ++/dts-v1/; ++/plugin/; ++ ++/* SDIO/SD/MMC on RP1 bank 0 */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&rp1_mmc0>; ++ frag0: __overlay__ { ++ status = "okay"; ++ pinctrl-0 = <&rp1_sdio0_22_27>; ++ pinctrl-names = "default"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&rp1_sdio_clk0>; ++ frag1: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/rp1.dtsi ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -962,7 +962,7 @@ + + rp1_mmc0: mmc@180000 { + reg = <0xc0 0x40180000 0x0 0x100>; +- compatible = "snps,dwcmshc-sdhci"; ++ compatible = "raspberrypi,rp1-dwcmshc"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core + &rp1_clocks RP1_CLK_SDIO_TIMER +@@ -978,7 +978,7 @@ + + rp1_mmc1: mmc@184000 { + reg = <0xc0 0x40184000 0x0 0x100>; +- compatible = "snps,dwcmshc-sdhci"; ++ compatible = "raspberrypi,rp1-dwcmshc"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core + &rp1_clocks RP1_CLK_SDIO_TIMER diff --git a/target/linux/bcm27xx/patches-6.1/950-1079-ASoC-bcm-audioinjector_octo-Add-soundcard-owner.patch b/target/linux/bcm27xx/patches-6.1/950-1079-ASoC-bcm-audioinjector_octo-Add-soundcard-owner.patch new file mode 100644 index 0000000000..aa025125e7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1079-ASoC-bcm-audioinjector_octo-Add-soundcard-owner.patch @@ -0,0 +1,22 @@ +From 020ee5029ab0b11e47696f538418105ccfdb44de Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 8 Nov 2023 19:17:33 +0000 +Subject: [PATCH] ASoC: bcm: audioinjector_octo: Add soundcard "owner" + +See: https://github.com/raspberrypi/linux/issues/5697 + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/audioinjector-octo-soundcard.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/bcm/audioinjector-octo-soundcard.c ++++ b/sound/soc/bcm/audioinjector-octo-soundcard.c +@@ -252,6 +252,7 @@ static const struct snd_soc_dapm_route a + + static struct snd_soc_card snd_soc_audioinjector_octo = { + .name = "audioinjector-octo-soundcard", ++ .owner = THIS_MODULE, + .dai_link = audioinjector_octo_dai, + .num_links = ARRAY_SIZE(audioinjector_octo_dai), + diff --git a/target/linux/bcm27xx/patches-6.1/950-1080-drivers-media-imx708-Adjust-broken-line-correction-p.patch b/target/linux/bcm27xx/patches-6.1/950-1080-drivers-media-imx708-Adjust-broken-line-correction-p.patch new file mode 100644 index 0000000000..60f489c6c0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1080-drivers-media-imx708-Adjust-broken-line-correction-p.patch @@ -0,0 +1,139 @@ +From f364e0eb8f973e1aa24a3c451d18e84247a8efcd Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 8 Nov 2023 10:57:45 +0000 +Subject: [PATCH] drivers: media: imx708: Adjust broken line correction + parameter + +In full-resolution mode, the LPF_INTENSITY_EN and LPF_INTENSITY +registers control Quad Bayer Re-mosaic broken line correction. +Expose this as a module parameter "qbc_adjust": zero disables +the correction and values in the range 2 to 5 set its strength. + +There is a trade-off between coloured and monochrome patterns. +The previous fixed value 4 could produce ladder/spots artefacts +in coloured textures. The new default value 2 may suit a wider +range of scenes. + +Signed-off-by: Nick Hollinghurst +--- + drivers/media/i2c/imx708.c | 50 ++++++++++++++++++++++++++++++++------ + 1 file changed, 42 insertions(+), 8 deletions(-) + +--- a/drivers/media/i2c/imx708.c ++++ b/drivers/media/i2c/imx708.c +@@ -20,6 +20,14 @@ + #include + #include + ++/* ++ * Parameter to adjust Quad Bayer re-mosaic broken line correction ++ * strength, used in full-resolution mode only. Set zero to disable. ++ */ ++static int qbc_adjust = 2; ++module_param(qbc_adjust, int, 0644); ++MODULE_PARM_DESC(qbc_adjust, "Quad Bayer broken line correction strength [0,2-5]"); ++ + #define IMX708_REG_VALUE_08BIT 1 + #define IMX708_REG_VALUE_16BIT 2 + +@@ -99,11 +107,17 @@ + + /* HDR exposure ratio (long:med == med:short) */ + #define IMX708_HDR_EXPOSURE_RATIO 4 +-#define IMX708_REG_MID_EXPOSURE 0x3116 +-#define IMX708_REG_SHT_EXPOSURE 0x0224 ++#define IMX708_REG_MID_EXPOSURE 0x3116 ++#define IMX708_REG_SHT_EXPOSURE 0x0224 + #define IMX708_REG_MID_ANALOG_GAIN 0x3118 + #define IMX708_REG_SHT_ANALOG_GAIN 0x0216 + ++/* QBC Re-mosaic broken line correction registers */ ++#define IMX708_LPF_INTENSITY_EN 0xC428 ++#define IMX708_LPF_INTENSITY_ENABLED 0x00 ++#define IMX708_LPF_INTENSITY_DISABLED 0x01 ++#define IMX708_LPF_INTENSITY 0xC429 ++ + /* + * Metadata buffer holds a variety of data, all sent with the same VC/DT (0x12). + * It comprises two scanlines (of up to 5760 bytes each, for 4608 pixels) +@@ -171,6 +185,9 @@ struct imx708_mode { + + /* HDR flag, used for checking if the current mode is HDR */ + bool hdr; ++ ++ /* Quad Bayer Re-mosaic flag */ ++ bool remosaic; + }; + + /* Default PDAF pixel correction gains */ +@@ -363,8 +380,6 @@ static const struct imx708_reg mode_4608 + {0x341f, 0x20}, + {0x3420, 0x00}, + {0x3421, 0xd8}, +- {0xC428, 0x00}, +- {0xC429, 0x04}, + {0x3366, 0x00}, + {0x3367, 0x00}, + {0x3368, 0x00}, +@@ -677,7 +692,8 @@ static const struct imx708_mode supporte + .pixel_rate = 595200000, + .exposure_lines_min = 8, + .exposure_lines_step = 1, +- .hdr = false ++ .hdr = false, ++ .remosaic = true + }, + { + /* regular 2x2 binned. */ +@@ -699,7 +715,8 @@ static const struct imx708_mode supporte + .pixel_rate = 585600000, + .exposure_lines_min = 4, + .exposure_lines_step = 2, +- .hdr = false ++ .hdr = false, ++ .remosaic = false + }, + { + /* 2x2 binned and cropped for 720p. */ +@@ -721,7 +738,8 @@ static const struct imx708_mode supporte + .pixel_rate = 566400000, + .exposure_lines_min = 4, + .exposure_lines_step = 2, +- .hdr = false ++ .hdr = false, ++ .remosaic = false + }, + }; + +@@ -746,7 +764,8 @@ static const struct imx708_mode supporte + .pixel_rate = 777600000, + .exposure_lines_min = 8 * IMX708_HDR_EXPOSURE_RATIO * IMX708_HDR_EXPOSURE_RATIO, + .exposure_lines_step = 2 * IMX708_HDR_EXPOSURE_RATIO * IMX708_HDR_EXPOSURE_RATIO, +- .hdr = true ++ .hdr = true, ++ .remosaic = false + } + }; + +@@ -1515,6 +1534,21 @@ static int imx708_start_streaming(struct + return ret; + } + ++ /* Quad Bayer re-mosaic adjustments (for full-resolution mode only) */ ++ if (imx708->mode->remosaic && qbc_adjust > 0) { ++ imx708_write_reg(imx708, IMX708_LPF_INTENSITY, ++ IMX708_REG_VALUE_08BIT, qbc_adjust); ++ imx708_write_reg(imx708, ++ IMX708_LPF_INTENSITY_EN, ++ IMX708_REG_VALUE_08BIT, ++ IMX708_LPF_INTENSITY_ENABLED); ++ } else { ++ imx708_write_reg(imx708, ++ IMX708_LPF_INTENSITY_EN, ++ IMX708_REG_VALUE_08BIT, ++ IMX708_LPF_INTENSITY_DISABLED); ++ } ++ + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx708->sd.ctrl_handler); + if (ret) diff --git a/target/linux/bcm27xx/patches-6.1/950-1082-drivers-media-cfe-Don-t-confuse-MHz-and-Mbps.patch b/target/linux/bcm27xx/patches-6.1/950-1082-drivers-media-cfe-Don-t-confuse-MHz-and-Mbps.patch new file mode 100644 index 0000000000..ea0ea396ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1082-drivers-media-cfe-Don-t-confuse-MHz-and-Mbps.patch @@ -0,0 +1,96 @@ +From 65407c54fb4119e528b70b329448269657e0941e Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 8 Nov 2023 10:05:05 +0000 +Subject: [PATCH] drivers: media: cfe: Don't confuse MHz and Mbps + +The driver was interchaning these units when talking about link rate. +Fix this to avoid confusion. Apart from the logging message change, +there is no function change in this commit. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 8 ++++---- + drivers/media/platform/raspberrypi/rp1_cfe/dphy.c | 10 +++++----- + drivers/media/platform/raspberrypi/rp1_cfe/dphy.h | 2 +- + 3 files changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -983,7 +983,7 @@ static void cfe_buffer_queue(struct vb2_ + spin_unlock_irqrestore(&cfe->state_lock, flags); + } + +-static u64 sensor_link_frequency(struct cfe_device *cfe) ++static u64 sensor_link_rate(struct cfe_device *cfe) + { + struct v4l2_mbus_framefmt *source_fmt; + struct v4l2_subdev_state *state; +@@ -1028,11 +1028,11 @@ static u64 sensor_link_frequency(struct + + /* x2 for DDR. */ + link_freq *= 2; +- cfe_info("Using a link frequency of %lld Hz\n", link_freq); ++ cfe_info("Using a link rate of %lld Mbps\n", link_freq / (1000 * 1000)); + return link_freq; + + err: +- cfe_err("Unable to determine sensor link frequency, using 999 MHz\n"); ++ cfe_err("Unable to determine sensor link rate, using 999 Mbps\n"); + return 999 * 1000000UL; + } + +@@ -1104,7 +1104,7 @@ static int cfe_start_streaming(struct vb + } + + cfe_dbg("Configuring CSI-2 block\n"); +- cfe->csi2.dphy.dphy_freq = sensor_link_frequency(cfe) / 1000000UL; ++ cfe->csi2.dphy.dphy_rate = sensor_link_rate(cfe) / 1000000UL; + csi2_open_rx(&cfe->csi2); + + cfe_dbg("Starting sensor streaming\n"); +--- a/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c +@@ -96,7 +96,7 @@ static uint8_t dphy_transaction(struct d + return get_tstdout(dphy); + } + +-static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t freq_mhz) ++static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t mbps) + { + /* See Table 5-1 on page 65 of dphy databook */ + static const u16 hsfreqrange_table[][2] = { +@@ -116,11 +116,11 @@ static void dphy_set_hsfreqrange(struct + }; + unsigned int i; + +- if (freq_mhz < 80 || freq_mhz > 1500) +- dphy_err("DPHY: Frequency %u MHz out of range\n", freq_mhz); ++ if (mbps < 80 || mbps > 1500) ++ dphy_err("DPHY: Datarate %u Mbps out of range\n", mbps); + + for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) { +- if (freq_mhz <= hsfreqrange_table[i][0]) ++ if (mbps <= hsfreqrange_table[i][0]) + break; + } + +@@ -139,7 +139,7 @@ static void dphy_init(struct dphy_data * + set_tstclr(dphy, 0); + usleep_range(15, 20); + +- dphy_set_hsfreqrange(dphy, dphy->dphy_freq); ++ dphy_set_hsfreqrange(dphy, dphy->dphy_rate); + + usleep_range(5, 10); + dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 1); +--- a/drivers/media/platform/raspberrypi/rp1_cfe/dphy.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.h +@@ -15,7 +15,7 @@ struct dphy_data { + + void __iomem *base; + +- u32 dphy_freq; ++ u32 dphy_rate; + u32 num_lanes; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1083-overlays-imx296-Fix-cam-port-override-for-regulators.patch b/target/linux/bcm27xx/patches-6.1/950-1083-overlays-imx296-Fix-cam-port-override-for-regulators.patch new file mode 100644 index 0000000000..1b6d2041f1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1083-overlays-imx296-Fix-cam-port-override-for-regulators.patch @@ -0,0 +1,25 @@ +From 6137fb168c08bd8c41c8421bf26f09ed29479f08 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 15 Nov 2023 08:25:11 +0000 +Subject: [PATCH] overlays: imx296: Fix cam port override for regulators + +The override was missing/incorrect for the regulator labels. + +Signed-off-by: Naushir Patuck +--- + arch/arm/boot/dts/overlays/imx296-overlay.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/imx296-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx296-overlay.dts +@@ -97,8 +97,9 @@ + cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, ++ <®_frag>, "target:0=",<&cam0_reg>, + <&imx296>, "clocks:0=",<&cam0_clk>, +- <&imx296>, "VANA-supply:0=",<&cam0_reg>; ++ <&imx296>, "avdd-supply:0=",<&cam0_reg>; + clock-frequency = <&clk_over>, "clock-frequency:0"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1148-overlays-ov5647-Regularise-vcm-node-label-name.patch b/target/linux/bcm27xx/patches-6.1/950-1148-overlays-ov5647-Regularise-vcm-node-label-name.patch new file mode 100644 index 0000000000..28017989a9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1148-overlays-ov5647-Regularise-vcm-node-label-name.patch @@ -0,0 +1,32 @@ +From 7443b602cb503b42dd0ae8e957e26decb420d632 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 10:15:15 +0000 +Subject: [PATCH] overlays: ov5647: Regularise vcm node label name + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/ov5647-overlay.dts | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts +@@ -15,7 +15,7 @@ + + #include "ov5647.dtsi" + +- vcm: ad5398@c { ++ vcm_node: ad5398@c { + compatible = "adi,ad5398"; + reg = <0x0c>; + status = "disabled"; +@@ -78,8 +78,8 @@ + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, + <&cam_node>, "avdd-supply:0=",<&cam0_reg>; +- vcm = <&vcm>, "status=okay", +- <&cam_node>,"lens-focus:0=", <&vcm>; ++ vcm = <&vcm_node>, "status=okay", ++ <&cam_node>,"lens-focus:0=", <&vcm_node>; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1149-overlays-ov5647-cam0-mode-should-use-cam0_reg.patch b/target/linux/bcm27xx/patches-6.1/950-1149-overlays-ov5647-cam0-mode-should-use-cam0_reg.patch new file mode 100644 index 0000000000..f079756133 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1149-overlays-ov5647-cam0-mode-should-use-cam0_reg.patch @@ -0,0 +1,27 @@ +From d484bef133af9c87d64899fc1e1d0be2a7c7785b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 10:16:10 +0000 +Subject: [PATCH] overlays: ov5647: cam0 mode should use cam0_reg + +When the cam0 parameter is used, the vcm should be updated to refer to +the cam0 regulator. + +See: https://github.com/raspberrypi/linux/issues/5722 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/ov5647-overlay.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts +@@ -77,7 +77,8 @@ + <®_frag>, "target:0=",<&cam0_reg>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +- <&cam_node>, "avdd-supply:0=",<&cam0_reg>; ++ <&cam_node>, "avdd-supply:0=",<&cam0_reg>, ++ <&vcm_node>, "VANA-supply:0=",<&cam0_reg>; + vcm = <&vcm_node>, "status=okay", + <&cam_node>,"lens-focus:0=", <&vcm_node>; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1150-w1-Disable-kernel-log-spam.patch b/target/linux/bcm27xx/patches-6.1/950-1150-w1-Disable-kernel-log-spam.patch new file mode 100644 index 0000000000..457a0e9ec5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1150-w1-Disable-kernel-log-spam.patch @@ -0,0 +1,25 @@ +From 0924b74687bd195b98f223814ff88b4227654e85 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 14:46:14 +0000 +Subject: [PATCH] w1: Disable kernel log spam + +See: https://forums.raspberrypi.com/viewtopic.php?p=2159344 + +Signed-off-by: Phil Elwell +--- + drivers/w1/w1.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/w1/w1.c ++++ b/drivers/w1/w1.c +@@ -742,8 +742,10 @@ int w1_attach_slave_device(struct w1_mas + atomic_set(&sl->refcnt, 1); + atomic_inc(&sl->master->refcnt); + dev->slave_count++; ++#if 0 + dev_info(&dev->dev, "Attaching one wire slave %02x.%012llx crc %02x\n", + rn->family, (unsigned long long)rn->id, rn->crc); ++#endif + + /* slave modules need to be loaded in a context with unlocked mutex */ + mutex_unlock(&dev->mutex); diff --git a/target/linux/bcm27xx/patches-6.1/950-1151-include-uapi-mbus-Add-a-media-bus-format-enum-for-16.patch b/target/linux/bcm27xx/patches-6.1/950-1151-include-uapi-mbus-Add-a-media-bus-format-enum-for-16.patch new file mode 100644 index 0000000000..b8933bcbb6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1151-include-uapi-mbus-Add-a-media-bus-format-enum-for-16.patch @@ -0,0 +1,21 @@ +From be8ca764e0530ec8ac18ca03c49e3cda13562d3a Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:21:05 +0000 +Subject: [PATCH] include: uapi: mbus: Add a media bus format enum for 16-bit + mono output + +Signed-off-by: Naushir Patuck +--- + include/uapi/linux/media-bus-format.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/uapi/linux/media-bus-format.h ++++ b/include/uapi/linux/media-bus-format.h +@@ -95,6 +95,7 @@ + #define MEDIA_BUS_FMT_YUYV12_2X12 0x201e + #define MEDIA_BUS_FMT_YVYU12_2X12 0x201f + #define MEDIA_BUS_FMT_Y14_1X14 0x202d ++#define MEDIA_BUS_FMT_Y16_1X16 0x202e + #define MEDIA_BUS_FMT_UYVY8_1X16 0x200f + #define MEDIA_BUS_FMT_VYUY8_1X16 0x2010 + #define MEDIA_BUS_FMT_YUYV8_1X16 0x2011 diff --git a/target/linux/bcm27xx/patches-6.1/950-1152-include-uapi-v4l2-Add-additional-pixel-formats-for-u.patch b/target/linux/bcm27xx/patches-6.1/950-1152-include-uapi-v4l2-Add-additional-pixel-formats-for-u.patch new file mode 100644 index 0000000000..56855184be --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1152-include-uapi-v4l2-Add-additional-pixel-formats-for-u.patch @@ -0,0 +1,73 @@ +From 9abab2e8e5cfbeae6e1b33cc3a5ed773e4e31774 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:25:39 +0000 +Subject: [PATCH] include: uapi: v4l2: Add additional pixel formats for use + with PiSP + +Add the following formats: + +- V4L2_PIX_FMT_RGB48/V4L2_PIX_FMT_BGR48 + 48-bit RGB where each colour sample is 16-bits. + +- V4L2_PIX_FMT_PISP_COMP1_MONO/V4L2_PIX_FMT_PISP_COMP2_MONO + 16-bit to 8-bit pisp compressed monochrome pixel format. + +Signed-off-by: Naushir Patuck +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 8 ++++++-- + include/uapi/linux/videodev2.h | 6 ++++++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1304,6 +1304,8 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_BGRX32: descr = "32-bit XBGR 8-8-8-8"; break; + case V4L2_PIX_FMT_RGBA32: descr = "32-bit RGBA 8-8-8-8"; break; + case V4L2_PIX_FMT_RGBX32: descr = "32-bit RGBX 8-8-8-8"; break; ++ case V4L2_PIX_FMT_BGR48: descr = "48-bit BGR 16-16-16"; break; ++ case V4L2_PIX_FMT_RGB48: descr = "48-bit RGB 16-16-16"; break; + case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break; + case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break; + case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break; +@@ -1510,11 +1512,13 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_PISP_COMP1_RGGB: + case V4L2_PIX_FMT_PISP_COMP1_GRBG: + case V4L2_PIX_FMT_PISP_COMP1_GBRG: +- case V4L2_PIX_FMT_PISP_COMP1_BGGR: descr = "PiSP Bayer Comp 1"; break; ++ case V4L2_PIX_FMT_PISP_COMP1_BGGR: ++ case V4L2_PIX_FMT_PISP_COMP1_MONO: descr = "PiSP Bayer Comp 1"; break; + case V4L2_PIX_FMT_PISP_COMP2_RGGB: + case V4L2_PIX_FMT_PISP_COMP2_GRBG: + case V4L2_PIX_FMT_PISP_COMP2_GBRG: +- case V4L2_PIX_FMT_PISP_COMP2_BGGR: descr = "PiSP Bayer Comp 2"; break; ++ case V4L2_PIX_FMT_PISP_COMP2_BGGR: ++ case V4L2_PIX_FMT_PISP_COMP2_MONO: descr = "PiSP Bayer Comp 2"; break; + default: + if (fmt->description[0]) + return; +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -582,6 +582,10 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */ + #define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */ + ++/* RGB formats (6 bytes per pixel) */ ++#define V4L2_PIX_FMT_BGR48 v4l2_fourcc('B', 'G', 'R', '6') /* 16 BGR-16-16-16 */ ++#define V4L2_PIX_FMT_RGB48 v4l2_fourcc('R', 'G', 'B', '6') /* 16 RGB-16-16-16 */ ++ + /* Grey formats */ + #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ + #define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */ +@@ -799,10 +803,12 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_PISP_COMP1_GRBG v4l2_fourcc('P', 'C', '1', 'G') + #define V4L2_PIX_FMT_PISP_COMP1_GBRG v4l2_fourcc('P', 'C', '1', 'g') + #define V4L2_PIX_FMT_PISP_COMP1_BGGR v4l2_fourcc('P', 'C', '1', 'B') ++#define V4L2_PIX_FMT_PISP_COMP1_MONO v4l2_fourcc('P', 'C', '1', 'M') + #define V4L2_PIX_FMT_PISP_COMP2_RGGB v4l2_fourcc('P', 'C', '2', 'R') + #define V4L2_PIX_FMT_PISP_COMP2_GRBG v4l2_fourcc('P', 'C', '2', 'G') + #define V4L2_PIX_FMT_PISP_COMP2_GBRG v4l2_fourcc('P', 'C', '2', 'g') + #define V4L2_PIX_FMT_PISP_COMP2_BGGR v4l2_fourcc('P', 'C', '2', 'B') ++#define V4L2_PIX_FMT_PISP_COMP2_MONO v4l2_fourcc('P', 'C', '2', 'M') + + /* SDR formats - used only for Software Defined Radio devices */ + #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1153-drivers-media-cfe-Add-16-bit-and-compressed-mono-for.patch b/target/linux/bcm27xx/patches-6.1/950-1153-drivers-media-cfe-Add-16-bit-and-compressed-mono-for.patch new file mode 100644 index 0000000000..607f23eeb3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1153-drivers-media-cfe-Add-16-bit-and-compressed-mono-for.patch @@ -0,0 +1,52 @@ +From 88d06a674009ad5b77234537527a800e6e0e88a3 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:28:55 +0000 +Subject: [PATCH] drivers: media: cfe: Add 16-bit and compressed mono format + support + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -249,28 +249,34 @@ static const struct cfe_fmt formats[] = + .code = MEDIA_BUS_FMT_Y10_1X10, + .depth = 10, + .csi_dt = 0x2b, +- .remap = { V4L2_PIX_FMT_Y16 }, ++ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO }, + }, + { + .fourcc = V4L2_PIX_FMT_Y12P, + .code = MEDIA_BUS_FMT_Y12_1X12, + .depth = 12, + .csi_dt = 0x2c, +- .remap = { V4L2_PIX_FMT_Y16 }, ++ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO }, + }, + { + .fourcc = V4L2_PIX_FMT_Y14P, + .code = MEDIA_BUS_FMT_Y14_1X14, + .depth = 14, + .csi_dt = 0x2d, +- .remap = { V4L2_PIX_FMT_Y16 }, ++ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO }, + }, + { + .fourcc = V4L2_PIX_FMT_Y16, ++ .code = MEDIA_BUS_FMT_Y16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, +- ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_MONO, ++ .code = MEDIA_BUS_FMT_Y16_1X16, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, + /* Embedded data format */ + { + .fourcc = V4L2_META_FMT_SENSOR_DATA, diff --git a/target/linux/bcm27xx/patches-6.1/950-1154-drivers-media-pisp_be-Add-mono-and-48-bit-RGB-pixel-.patch b/target/linux/bcm27xx/patches-6.1/950-1154-drivers-media-pisp_be-Add-mono-and-48-bit-RGB-pixel-.patch new file mode 100644 index 0000000000..2ea4abd112 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1154-drivers-media-pisp_be-Add-mono-and-48-bit-RGB-pixel-.patch @@ -0,0 +1,72 @@ +From 2affda8d2b172aa0fd22778983d983fc9522e621 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:29:47 +0000 +Subject: [PATCH] drivers: media: pisp_be: Add mono and 48-bit RGB pixel format + support + +Signed-off-by: Naushir Patuck +--- + .../raspberrypi/pisp_be/pisp_be_formats.h | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +@@ -234,6 +234,24 @@ static const struct pisp_be_format suppo + .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, + .colorspace_default = V4L2_COLORSPACE_SRGB, + }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB48, ++ .align = 64, ++ .bit_depth = 48, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_BGR48, ++ .align = 64, ++ .bit_depth = 48, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, + /* Bayer formats - 8-bit */ + { + .fourcc = V4L2_PIX_FMT_SRGGB8, +@@ -457,6 +475,33 @@ static const struct pisp_be_format suppo + .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, + .colorspace_default = V4L2_COLORSPACE_RAW, + }, ++ /* Greyscale Formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .bit_depth = 8, ++ .align = 32, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_MONO, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, + /* Opaque BE format for HW verification. */ + { + .fourcc = V4L2_PIX_FMT_RPI_BE, diff --git a/target/linux/bcm27xx/patches-6.1/950-1155-ASoC-dwc-Remove-check-in-set_bclk_ratio-handling.patch b/target/linux/bcm27xx/patches-6.1/950-1155-ASoC-dwc-Remove-check-in-set_bclk_ratio-handling.patch new file mode 100644 index 0000000000..88bb61a4c3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1155-ASoC-dwc-Remove-check-in-set_bclk_ratio-handling.patch @@ -0,0 +1,32 @@ +From 52545628c07be2fd1c9df598a17130d92f12da23 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 15:17:34 +0000 +Subject: [PATCH] ASoC: dwc: Remove check in set_bclk_ratio handling + +A check added to dw_i2s_set_bclk_ratio that the data format is +consistent with the ratio seems reasonable but breaks when the +ratio is changed before the format. Remove the check - it is +unnecessary. + +See: https://github.com/raspberrypi/linux/issues/5724 +Fixes: 9c6694c24f26 ("ASOC: dwc: Fix 16-bit audio handling") + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -427,11 +427,8 @@ static int dw_i2s_set_bclk_ratio(struct + unsigned int ratio) + { + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); +- struct i2s_clk_config_data *config = &dev->config; + + dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio); +- if (ratio < config->data_width * 2) +- return -EINVAL; + + switch (ratio) { + case 32: diff --git a/target/linux/bcm27xx/patches-6.1/950-1159-overlays-README-Fix-cut-and-paste-errors.patch b/target/linux/bcm27xx/patches-6.1/950-1159-overlays-README-Fix-cut-and-paste-errors.patch new file mode 100644 index 0000000000..30cc82b0cd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1159-overlays-README-Fix-cut-and-paste-errors.patch @@ -0,0 +1,39 @@ +From 5a0aa24b8ff58ceaf98c62670156bef7f48ed32b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 21 Nov 2023 15:08:38 +0000 +Subject: [PATCH] overlays: README: Fix cut-and-paste errors + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1673,7 +1673,7 @@ Params: 24db_digital_gain Allow ga + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) +- slave Force DAC+ Pro into slave mode, using Pi as ++ slave Force AMP100 into slave mode, using Pi as + master for bit clock and frame clock. + leds_off If set to 'true' the onboard indicator LEDs + are switched off at all times. +@@ -1713,7 +1713,7 @@ Params: 24db_digital_gain Allow ga + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) +- slave Force DAC+ Pro into slave mode, using Pi as ++ slave Force DAC+ into slave mode, using Pi as + master for bit clock and frame clock. + leds_off If set to 'true' the onboard indicator LEDs + are switched off at all times. +@@ -1736,7 +1736,7 @@ Params: 24db_digital_gain Allow ga + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) +- slave Force DAC+ Pro into slave mode, using Pi as ++ slave Force DAC+ADC into slave mode, using Pi as + master for bit clock and frame clock. + leds_off If set to 'true' the onboard indicator LEDs + are switched off at all times. diff --git a/target/linux/bcm27xx/patches-6.1/950-1160-media-i2c-ov7251-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch b/target/linux/bcm27xx/patches-6.1/950-1160-media-i2c-ov7251-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch new file mode 100644 index 0000000000..36565bf2d6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1160-media-i2c-ov7251-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch @@ -0,0 +1,38 @@ +From e60fbc34aa98b3ba2c9338ad628fc8d8137e9065 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 14 Nov 2023 18:36:19 +0000 +Subject: [PATCH] media/i2c: ov7251: Switch from V4L2_CID_GAIN to + V4L2_CID_ANALOGUE_GAIN + +The mainline driver has implemented analogue gain using the control +V4L2_CID_GAIN instead of V4L2_CID_ANALOGUE_GAIN. + +libcamera requires V4L2_CID_ANALOGUE_GAIN, and therefore fails. + +Update the driver to use V4L2_CID_ANALOGUE_GAIN. + +Signed-off-by: Dave Stevenson +--- + drivers/media/i2c/ov7251.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/i2c/ov7251.c ++++ b/drivers/media/i2c/ov7251.c +@@ -1063,7 +1063,7 @@ static int ov7251_s_ctrl(struct v4l2_ctr + case V4L2_CID_EXPOSURE: + ret = ov7251_set_exposure(ov7251, ctrl->val); + break; +- case V4L2_CID_GAIN: ++ case V4L2_CID_ANALOGUE_GAIN: + ret = ov7251_set_gain(ov7251, ctrl->val); + break; + case V4L2_CID_TEST_PATTERN: +@@ -1588,7 +1588,7 @@ static int ov7251_init_ctrls(struct ov72 + ov7251->exposure = v4l2_ctrl_new_std(&ov7251->ctrls, &ov7251_ctrl_ops, + V4L2_CID_EXPOSURE, 1, 32, 1, 32); + ov7251->gain = v4l2_ctrl_new_std(&ov7251->ctrls, &ov7251_ctrl_ops, +- V4L2_CID_GAIN, 16, 1023, 1, 16); ++ V4L2_CID_ANALOGUE_GAIN, 16, 1023, 1, 16); + v4l2_ctrl_new_std_menu_items(&ov7251->ctrls, &ov7251_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov7251_test_pattern_menu) - 1, diff --git a/target/linux/bcm27xx/patches-6.1/950-1161-drm-vc4-Drop-planes-that-are-completely-off-screen.patch b/target/linux/bcm27xx/patches-6.1/950-1161-drm-vc4-Drop-planes-that-are-completely-off-screen.patch new file mode 100644 index 0000000000..8cdbb51d55 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1161-drm-vc4-Drop-planes-that-are-completely-off-screen.patch @@ -0,0 +1,63 @@ +From 444884f7b62bfe5ef313dd1d47f81a40e695ab0b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 17 Nov 2023 14:43:44 +0000 +Subject: [PATCH] drm/vc4: Drop planes that are completely off-screen + +It is permitted for a plane to be configured such that none +of it is on-screen via either negative dest rectangle X,Y +offset, or just an offset that is greater than the crtc +dimensions. + +These planes were resized via drm_atomic_helper_check_plane_state +such that the source rectangle had a zero width or height, but +they still created a dlist entry even though they contributed +no pixels. In the case of vc6_plane_mode_set, that it could result +in negative values being written into registers, which caused +incorrect behaviour. + +Drop planes that result in a source width or height of 0 pixels +to avoid the incorrect rendering. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1108,6 +1108,12 @@ static int vc4_plane_mode_set(struct drm + width = vc4_state->src_w[0] >> 16; + height = vc4_state->src_h[0] >> 16; + ++ if (!width || !height) { ++ /* 0 source size probably means the plane is offscreen */ ++ vc4_state->dlist_initialized = 1; ++ return 0; ++ } ++ + /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB + * and 4:4:4, scl1 should be set to scl0 so both channels of + * the scaler do the same thing. For YUV, the Y plane needs +@@ -1623,6 +1629,12 @@ static int vc6_plane_mode_set(struct drm + width = vc4_state->src_w[0] >> 16; + height = vc4_state->src_h[0] >> 16; + ++ if (!width || !height) { ++ /* 0 source size probably means the plane is offscreen */ ++ vc4_state->dlist_initialized = 1; ++ return 0; ++ } ++ + /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB + * and 4:4:4, scl1 should be set to scl0 so both channels of + * the scaler do the same thing. For YUV, the Y plane needs +@@ -1994,6 +2006,9 @@ int vc4_plane_atomic_check(struct drm_pl + if (ret) + return ret; + ++ if (!vc4_state->src_w[0] || !vc4_state->src_h[0]) ++ return 0; ++ + ret = vc4_plane_allocate_lbm(new_plane_state); + if (ret) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-1162-drm-bridge-display-connector-Select-DRM_KMS_HELPER.patch b/target/linux/bcm27xx/patches-6.1/950-1162-drm-bridge-display-connector-Select-DRM_KMS_HELPER.patch new file mode 100644 index 0000000000..270975e587 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1162-drm-bridge-display-connector-Select-DRM_KMS_HELPER.patch @@ -0,0 +1,29 @@ +From 91ad217f93232fb3a0b52487fec67860fb29e93a Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 17 Nov 2023 14:50:11 +0000 +Subject: [PATCH] drm/bridge: display-connector: Select DRM_KMS_HELPER + +Commit 7cd70656d128 ("drm/bridge: display-connector: implement +bus fmts callbacks") added use of drm_atomic_helper_bridge_* +functions, but didn't select the dependency of DRM_KMS_HELPER. +If nothing else selected that dependency it resulted in a +build failure. + +Select the missing dependency. + +Fixes: 7cd70656d128 ("drm/bridge: display-connector: implement bus fmts callbacks") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/bridge/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/bridge/Kconfig ++++ b/drivers/gpu/drm/bridge/Kconfig +@@ -67,6 +67,7 @@ config DRM_CROS_EC_ANX7688 + config DRM_DISPLAY_CONNECTOR + tristate "Display connector support" + depends on OF ++ select DRM_KMS_HELPER + help + Driver for display connectors with support for DDC and hot-plug + detection. Most display controllers handle display connectors diff --git a/target/linux/bcm27xx/patches-6.1/950-1163-drm-vc4-Free-the-dlist-alloc-immediately-if-it-never.patch b/target/linux/bcm27xx/patches-6.1/950-1163-drm-vc4-Free-the-dlist-alloc-immediately-if-it-never.patch new file mode 100644 index 0000000000..49359362fe --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1163-drm-vc4-Free-the-dlist-alloc-immediately-if-it-never.patch @@ -0,0 +1,56 @@ +From 51712a6493bf8824419f51ca7950e7d88f48b699 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 22 Nov 2023 18:36:54 +0000 +Subject: [PATCH] drm: vc4: Free the dlist alloc immediately if it never hit + the hw + +atomic_check creates a state, and allocates the dlist memory for +it such that atomic_flush can not fail. + +On destroy that dlist allocation was being put in the stale list, +even though it had never been programmed into the hardware, +therefore doing lots of atomic_checks could consume all the dlist +memory and fail. + +If the dlist has never been programmed into the hardware, then +free it immediately. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_hvs.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -696,6 +696,7 @@ struct vc4_hvs_dlist_allocation { + struct drm_mm_node mm_node; + unsigned int channel; + u8 target_frame_count; ++ bool dlist_programmed; + }; + + struct vc4_crtc_state { +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -697,8 +697,11 @@ void vc4_hvs_mark_dlist_entry_stale(stru + * Kunit tests run with a mock device and we consider any hardware + * access a test failure. Let's free the dlist allocation right away if + * we're running under kunit, we won't risk a dlist corruption anyway. ++ * ++ * Likewise if the allocation was only checked and never programmed, we ++ * can destroy the allocation immediately. + */ +- if (kunit_get_current_test()) { ++ if (kunit_get_current_test() || !alloc->dlist_programmed) { + spin_lock_irqsave(&hvs->mm_lock, flags); + vc4_hvs_free_dlist_entry_locked(hvs, alloc); + spin_unlock_irqrestore(&hvs->mm_lock, flags); +@@ -1201,6 +1204,7 @@ static void vc4_hvs_install_dlist(struct + return; + + WARN_ON(!vc4_state->mm); ++ vc4_state->mm->dlist_programmed = true; + + if (vc4->gen >= VC4_GEN_6) + HVS_WRITE(SCALER6_DISPX_LPTRS(vc4_state->assigned_channel), diff --git a/target/linux/bcm27xx/patches-6.1/950-1164-input-edt-ft5x06-Include-I2C-details-in-names-for-th.patch b/target/linux/bcm27xx/patches-6.1/950-1164-input-edt-ft5x06-Include-I2C-details-in-names-for-th.patch new file mode 100644 index 0000000000..131e502406 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1164-input-edt-ft5x06-Include-I2C-details-in-names-for-th.patch @@ -0,0 +1,48 @@ +From 2a6c3115f4142e23ca10c984d7f65ac8fb901cc2 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 8 Nov 2023 15:50:39 +0000 +Subject: [PATCH] input: edt-ft5x06: Include I2C details in names for the + devices + +libinput uses the input device name alone. If you have two +identical input devices, then there is no way to differentiate +between them, and in the case of touchscreens that means no +way to associate them with the appropriate display device. + +Add the I2C bus and address to the start of the input device +name so that the name is always unique within the system. + +Signed-off-by: Dave Stevenson +--- + drivers/input/touchscreen/edt-ft5x06.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -67,6 +67,7 @@ + #define TOUCH_EVENT_RESERVED 0x03 + + #define EDT_NAME_LEN 23 ++#define EDT_NAME_PREFIX_LEN 8 + #define EDT_SWITCH_MODE_RETRIES 10 + #define EDT_SWITCH_MODE_DELAY 5 /* msec */ + #define EDT_RAW_DATA_RETRIES 100 +@@ -134,7 +135,7 @@ struct edt_ft5x06_ts_data { + int max_support_points; + unsigned int known_ids; + +- char name[EDT_NAME_LEN]; ++ char name[EDT_NAME_PREFIX_LEN + EDT_NAME_LEN]; + char fw_version[EDT_NAME_LEN]; + int init_td_status; + +@@ -965,6 +966,9 @@ static int edt_ft5x06_ts_identify(struct + char *model_name = tsdata->name; + char *fw_version = tsdata->fw_version; + ++ snprintf(model_name, EDT_NAME_PREFIX_LEN, "%s ", dev_name(&client->dev)); ++ model_name += strlen(model_name); ++ + /* see what we find if we assume it is a M06 * + * if we get less than EDT_NAME_LEN, we don't want + * to have garbage in there diff --git a/target/linux/bcm27xx/patches-6.1/950-1165-input-goodix-Include-I2C-details-in-names-for-the-de.patch b/target/linux/bcm27xx/patches-6.1/950-1165-input-goodix-Include-I2C-details-in-names-for-the-de.patch new file mode 100644 index 0000000000..4b529e66f5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1165-input-goodix-Include-I2C-details-in-names-for-the-de.patch @@ -0,0 +1,52 @@ +From a420bbde05f8a6691b0c3e0830092e443365aaa7 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 8 Nov 2023 16:20:27 +0000 +Subject: [PATCH] input: goodix: Include I2C details in names for the devices + +libinput uses the input device name alone. If you have two +identical input devices, then there is no way to differentiate +between them, and in the case of touchscreens that means no +way to associate them with the appropriate display device. + +Add the I2C bus and address to the start of the input device +name so that the name is always unique within the system. + +Signed-off-by: Dave Stevenson +--- + drivers/input/touchscreen/goodix.c | 5 ++++- + drivers/input/touchscreen/goodix.h | 3 +++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/input/touchscreen/goodix.c ++++ b/drivers/input/touchscreen/goodix.c +@@ -1211,7 +1211,10 @@ static int goodix_configure_dev(struct g + return -ENOMEM; + } + +- ts->input_dev->name = "Goodix Capacitive TouchScreen"; ++ snprintf(ts->name, GOODIX_NAME_MAX_LEN, "%s Goodix Capacitive TouchScreen", ++ dev_name(&ts->client->dev)); ++ ++ ts->input_dev->name = ts->name; + ts->input_dev->phys = "input/ts"; + ts->input_dev->id.bustype = BUS_I2C; + ts->input_dev->id.vendor = 0x0416; +--- a/drivers/input/touchscreen/goodix.h ++++ b/drivers/input/touchscreen/goodix.h +@@ -57,6 +57,8 @@ + #define GOODIX_CONFIG_MAX_LENGTH 240 + #define GOODIX_MAX_KEYS 7 + ++#define GOODIX_NAME_MAX_LEN 38 ++ + enum goodix_irq_pin_access_method { + IRQ_PIN_ACCESS_NONE, + IRQ_PIN_ACCESS_GPIO, +@@ -91,6 +93,7 @@ struct goodix_ts_data { + enum gpiod_flags gpiod_rst_flags; + char id[GOODIX_ID_MAX_LEN + 1]; + char cfg_name[64]; ++ char name[GOODIX_NAME_MAX_LEN]; + u16 version; + bool reset_controller_at_probe; + bool load_cfg_from_disk; diff --git a/target/linux/bcm27xx/patches-6.1/950-1166-drm-vc4-Block-swiotlb-bounce-buffers-being-imported-.patch b/target/linux/bcm27xx/patches-6.1/950-1166-drm-vc4-Block-swiotlb-bounce-buffers-being-imported-.patch new file mode 100644 index 0000000000..c40b77c957 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1166-drm-vc4-Block-swiotlb-bounce-buffers-being-imported-.patch @@ -0,0 +1,84 @@ +From a984fda6b2c24dbf1ca21924f99c8f9418f5765e Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 22 Nov 2023 19:17:44 +0000 +Subject: [PATCH] drm: vc4: Block swiotlb bounce buffers being imported as + dmabuf + +The dmabuf import already checks that the backing buffer is contiguous +and rejects it if it isn't. vc4 also requires that the buffer is +in the bottom 1GB of RAM, and this is all correctly defined via +dma-ranges. + +However the kernel silently uses swiotlb to bounce dma buffers +around if they are in the wrong region. This relies on dma sync +functions to be called in order to copy the data to/from the +bounce buffer. + +DRM is based on all memory allocations being coherent with the +GPU so that any updates to a framebuffer will be acted on without +the need for any additional update. This is fairly fundamentally +incompatible with needing to call dma_sync_ to handle the bounce +buffer copies, and therefore we have to detect and reject mappings +that use bounce buffers. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -175,6 +176,19 @@ static void vc4_close(struct drm_device + kfree(vc4file); + } + ++struct drm_gem_object * ++vc4_prime_import_sg_table(struct drm_device *dev, ++ struct dma_buf_attachment *attach, ++ struct sg_table *sgt) ++{ ++ phys_addr_t phys = dma_to_phys(dev->dev, sg_dma_address(sgt->sgl)); ++ ++ if (is_swiotlb_buffer(dev->dev, phys)) ++ return ERR_PTR(-EINVAL); ++ ++ return drm_gem_dma_prime_import_sg_table(dev, attach, sgt); ++} ++ + DEFINE_DRM_GEM_FOPS(vc4_drm_fops); + + static const struct drm_ioctl_desc vc4_drm_ioctls[] = { +@@ -211,7 +225,11 @@ const struct drm_driver vc4_drm_driver = + + .gem_create_object = vc4_create_object, + +- DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc4_bo_dumb_create), ++ .dumb_create = vc4_bo_dumb_create, ++ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, ++ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, ++ .gem_prime_import_sg_table = vc4_prime_import_sg_table, ++ .gem_prime_mmap = drm_gem_prime_mmap, + + .ioctls = vc4_drm_ioctls, + .num_ioctls = ARRAY_SIZE(vc4_drm_ioctls), +@@ -234,7 +252,11 @@ const struct drm_driver vc5_drm_driver = + .debugfs_init = vc4_debugfs_init, + #endif + +- DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc5_dumb_create), ++ .dumb_create = vc5_dumb_create, ++ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, ++ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, ++ .gem_prime_import_sg_table = vc4_prime_import_sg_table, ++ .gem_prime_mmap = drm_gem_prime_mmap, + + .fops = &vc4_drm_fops, + diff --git a/target/linux/bcm27xx/patches-6.1/950-1167-overlays-i2c-sensor-Add-adt7410-support.patch b/target/linux/bcm27xx/patches-6.1/950-1167-overlays-i2c-sensor-Add-adt7410-support.patch new file mode 100644 index 0000000000..c7c9daba3f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1167-overlays-i2c-sensor-Add-adt7410-support.patch @@ -0,0 +1,75 @@ +From 77a01f7da77446277139d8e9ce63f078cbe1ecfe Mon Sep 17 00:00:00 2001 +From: Kenny +Date: Wed, 22 Nov 2023 16:22:37 -0800 +Subject: [PATCH] overlays: i2c-sensor: Add adt7410 support + +See https://github.com/raspberrypi/linux/pull/5738 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 12 ++++++++---- + .../boot/dts/overlays/i2c-sensor-common.dtsi | 18 +++++++++++++++++- + 2 files changed, 25 insertions(+), 5 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2144,10 +2144,14 @@ Name: i2c-sensor + Info: Adds support for a number of I2C barometric pressure, temperature, + light level and chemical sensors on i2c_arm + Load: dtoverlay=i2c-sensor,= +-Params: addr Set the address for the BH1750, BME280, BME680, +- BMP280, BMP380, CCS811, DS1621, HDC100X, JC42, +- LM75, MCP980x, MPU6050, MPU9250, MS5637, MS5803, +- MS5805, MS5837, MS8607, SHT3x or TMP102 ++Params: addr Set the address for the ADT7410, BH1750, BME280, ++ BME680, BMP280, BMP380, CCS811, DS1621, HDC100X, ++ JC42, LM75, MCP980x, MPU6050, MPU9250, MS5637, ++ MS5803, MS5805, MS5837, MS8607, SHT3x or TMP102 ++ ++ adt7410 Select the Analog Devices ADT7410 and ADT7420 ++ temperature sensors ++ Valid address 0x48-0x4b, default 0x48 + + aht10 Select the Aosong AHT10 temperature and humidity + sensor +--- a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi +@@ -508,6 +508,21 @@ + }; + }; + ++ fragment@34 { ++ target = <&i2cbus>; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ adt7410: adt7410@48 { ++ compatible = "adi,adt7410", "adi,adt7420"; ++ reg = <0x48>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ + __overrides__ { + bme280 = <0>,"+0"; + bmp085 = <0>,"+1"; +@@ -543,6 +558,7 @@ + mpu9250 = <0>,"+29"; + bno055 = <0>,"+31"; + sht4x = <0>,"+32"; ++ adt7410 = <0>,"+34"; + + addr = <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0", + <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0", +@@ -552,7 +568,7 @@ + <&ms5837>,"reg:0", <&ms8607>,"reg:0", + <&mpu6050>,"reg:0", <&mpu9250>,"reg:0", + <&bno055>,"reg:0", <&sht4x>,"reg:0", +- <&bmp380>,"reg:0"; ++ <&bmp380>,"reg:0", <&adt7410>,"reg:0"; + int_pin = <&max30102>, "interrupts:0", + <&mpu6050>, "interrupts:0", + <&mpu9250>, "interrupts:0"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1168-overlays-hat_map-Add-pisound-mapping.patch b/target/linux/bcm27xx/patches-6.1/950-1168-overlays-hat_map-Add-pisound-mapping.patch new file mode 100644 index 0000000000..2620a598f7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1168-overlays-hat_map-Add-pisound-mapping.patch @@ -0,0 +1,26 @@ +From 7c185b18a1c6a6cd6ab8805fef03a4a8c9931656 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 24 Nov 2023 13:57:09 +0000 +Subject: [PATCH] overlays: hat_map: Add pisound mapping + +See: https://github.com/raspberrypi/linux/issues/5741 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/hat_map.dts | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/overlays/hat_map.dts ++++ b/arch/arm/boot/dts/overlays/hat_map.dts +@@ -6,6 +6,11 @@ + overlay = "iqaudio-codec"; + }; + ++ pisound { ++ uuid = [ a7ee5d28 da03 41f5 bbd7 20438a4bec5d ]; ++ overlay = "pisound"; ++ }; ++ + recalbox-rgbdual { + uuid = [ 1c955808 681f 4bbc a2ef b7ea47cd388e ]; + overlay = "recalboxrgbdual"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1169-drm-vc4-Set-TV-margins-on-the-composite-connector-st.patch b/target/linux/bcm27xx/patches-6.1/950-1169-drm-vc4-Set-TV-margins-on-the-composite-connector-st.patch new file mode 100644 index 0000000000..05da5d38c5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1169-drm-vc4-Set-TV-margins-on-the-composite-connector-st.patch @@ -0,0 +1,47 @@ +From bc76ab2e772242d0d92d38b2a5648485ee1a1b44 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20B=C3=BCchler?= +Date: Sun, 19 Nov 2023 01:22:20 +0100 +Subject: [PATCH] drm/vc4: Set TV margins on the composite connector state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Raspberry Pi bootloader can pass a set of margin values to the +kernel cmdline as part of the video= option. These should result in +black borders on the output to compensate for TVs where the visible area +on the screen is smaller than the full extents of the video image. + +With the VC4 driver this currently works on an HDMI connector, but not +on a composite video connector. + +The TV margins from the kernel cmdline are available in the +drm_cmdline_mode structure of the composite video connector. Apply them +to the connector state in the connector reset function. This is how it +is implemented for the VC4 HDMI connector. + +Signed-off-by: Michael Büchler +--- + drivers/gpu/drm/vc4/vc4_vec.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_vec.c ++++ b/drivers/gpu/drm/vc4/vc4_vec.c +@@ -436,6 +436,9 @@ static void vc4_vec_connector_reset(stru + /* preserve TV standard */ + if (connector->state) + connector->state->tv.mode = vc4_vec_get_default_mode(connector); ++ ++ /* apply TV margins from the cmdline_mode */ ++ drm_atomic_helper_connector_tv_reset(connector); + } + + static int vc4_vec_connector_atomic_check(struct drm_connector *conn, +@@ -483,6 +486,8 @@ static int vc4_vec_connector_init(struct + + drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs); + ++ drm_connector_attach_tv_margin_properties(connector); ++ + drm_object_attach_property(&connector->base, + dev->mode_config.tv_mode_property, + vc4_vec_get_default_mode(connector)); diff --git a/target/linux/bcm27xx/patches-6.1/950-1170-drm-panel-jdi-lt070me05000-Add-prepare_upstream_firs.patch b/target/linux/bcm27xx/patches-6.1/950-1170-drm-panel-jdi-lt070me05000-Add-prepare_upstream_firs.patch new file mode 100644 index 0000000000..62e408b514 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1170-drm-panel-jdi-lt070me05000-Add-prepare_upstream_firs.patch @@ -0,0 +1,26 @@ +From 63d8c0f5185169058384142547655fc038aae0bf Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 9 Aug 2023 21:04:40 +0100 +Subject: [PATCH] drm: panel: jdi-lt070me05000: Add prepare_upstream_first flag + +The panel driver wants to send DCS commands from the prepare +hook, therefore the DSI host wants to be pre_enabled first. +Set the flag to achieve this. + +https://forums.raspberrypi.com/viewtopic.php?t=354708 + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/panel/panel-jdi-lt070me05000.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c ++++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +@@ -437,6 +437,7 @@ static int jdi_panel_add(struct jdi_pane + return ret; + } + ++ jdi->base.prepare_upstream_first = true; + drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1172-drivers-media-cfe-Find-the-source-pads-on-the-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-1172-drivers-media-cfe-Find-the-source-pads-on-the-sensor.patch new file mode 100644 index 0000000000..e1f16d0171 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1172-drivers-media-cfe-Find-the-source-pads-on-the-sensor.patch @@ -0,0 +1,55 @@ +From 76b1bbf3ec3be0afdc768863ab7e9bbd2734b97b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 24 Nov 2023 14:29:57 +0000 +Subject: [PATCH] drivers: media: cfe: Find the source pads on the sensor + entity + +The driver was assuming that pad 0 on the sensor entity was the +appropriate source pad, but this isn't necessarily the case. +With video-mux, it has the sink pads first, and then the source +pad as the last one. + +Iterate through the sensor pads to find the relevant source pads. + +Signed-off-by: Dave Stevenson +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -1826,7 +1826,7 @@ static void cfe_unregister_nodes(struct + + static int cfe_link_node_pads(struct cfe_device *cfe) + { +- unsigned int i; ++ unsigned int i, source_pad = 0; + int ret; + + for (i = 0; i < CSI2_NUM_CHANNELS; i++) { +@@ -1835,14 +1835,23 @@ static int cfe_link_node_pads(struct cfe + if (!check_state(cfe, NODE_REGISTERED, i)) + continue; + +- if (i < cfe->sensor->entity.num_pads) { ++ /* Find next source pad */ ++ while (source_pad < cfe->sensor->entity.num_pads && ++ !(cfe->sensor->entity.pads[source_pad].flags & ++ MEDIA_PAD_FL_SOURCE)) ++ source_pad++; ++ ++ if (source_pad < cfe->sensor->entity.num_pads) { + /* Sensor -> CSI2 */ +- ret = media_create_pad_link(&cfe->sensor->entity, i, ++ ret = media_create_pad_link(&cfe->sensor->entity, source_pad, + &cfe->csi2.sd.entity, i, + MEDIA_LNK_FL_IMMUTABLE | + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; ++ ++ /* Dealt with that source_pad, look at the next one next time */ ++ source_pad++; + } + + /* CSI2 channel # -> /dev/video# */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1173-dtoverlays-Add-option-for-cam0-to-camera-mux-Nport-o.patch b/target/linux/bcm27xx/patches-6.1/950-1173-dtoverlays-Add-option-for-cam0-to-camera-mux-Nport-o.patch new file mode 100644 index 0000000000..09cdcc7928 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1173-dtoverlays-Add-option-for-cam0-to-camera-mux-Nport-o.patch @@ -0,0 +1,101 @@ +From 08c5904ad00ffc54d37058ead19814f8a85f6f39 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 27 Nov 2023 14:50:58 +0000 +Subject: [PATCH] dtoverlays: Add option for cam0 to camera-mux-Nport overlays + +Seeing as the mux can be connected to either CAM/DISP1 or +CAM/DISP0 on a Pi5, add a cam0 override to allow configuration +of which is used. Default (as with all camera overlays) is CAM/DISP1. + +The overlay does NOT update the camera regulator used by all the +sensors as doing so would be a nightmare. The Arducam mulitplexer +boards these overlays are initially supporting seem to tie the +regulator GPIO for all the sensors high anyway. +If it was viewed as necessary, then creating an additional +regulator that listed cam[01]_reg as the parent should work. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 4 ++++ + arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts | 7 +++++-- + arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts | 7 +++++-- + 3 files changed, 14 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -823,6 +823,8 @@ Params: cam0-arducam-64mp Select A + cam1-ov9281 Select OV9281 for camera on port 1 + cam1-imx290-clk-freq Set clock frequency for an IMX290 on port 1 + ++ cam0 Connect the mux to CAM0 port (default is CAM1) ++ + + Name: camera-mux-4port + Info: Configures a 4 port camera multiplexer +@@ -878,6 +880,8 @@ Params: cam0-arducam-64mp Select A + cam3-ov9281 Select OV9281 for camera on port 3 + cam3-imx290-clk-freq Set clock frequency for an IMX290 on port 3 + ++ cam0 Connect the mux to CAM0 port (default is CAM1) ++ + + Name: cap1106 + Info: Enables the ability to use the cap1106 touch sensor as a keyboard +--- a/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts +@@ -77,7 +77,7 @@ + }; + + /* Mux define */ +- fragment@200 { ++ i2c_frag: fragment@200 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -294,7 +294,7 @@ + }; + }; + +- fragment@201 { ++ csi_frag: fragment@201 { + target = <&csi1>; + __overlay__ { + status = "okay"; +@@ -501,5 +501,8 @@ + <&imx290_0>,"clock-frequency:0"; + cam1-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_1>,"clock-frequency:0"; ++ ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&csi_frag>, "target:0=",<&csi0>; + }; + }; +--- a/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts +@@ -135,7 +135,7 @@ + }; + + /* Mux define */ +- fragment@200 { ++ i2c_frag: fragment@200 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -552,7 +552,7 @@ + }; + }; + +- fragment@201 { ++ csi_frag: fragment@201 { + target = <&csi1>; + __overlay__ { + status = "okay"; +@@ -872,5 +872,8 @@ + <&imx290_2>,"clock-frequency:0"; + cam3-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_3>,"clock-frequency:0"; ++ ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&csi_frag>, "target:0=",<&csi0>; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1174-ASoC-dwc-Permit-sample-rates-up-to-384kHz.patch b/target/linux/bcm27xx/patches-6.1/950-1174-ASoC-dwc-Permit-sample-rates-up-to-384kHz.patch new file mode 100644 index 0000000000..258b9de01c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1174-ASoC-dwc-Permit-sample-rates-up-to-384kHz.patch @@ -0,0 +1,26 @@ +From 6fac5d5ed6d023733ef7304afc88c8d89467a204 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 27 Nov 2023 12:16:04 +0000 +Subject: [PATCH] ASoC: dwc: Permit sample rates up to 384kHz + +The BCM2835 I2S block advertises clock rates up to 384kHz, and there's +no reason why RP1's DWC I2S block shouldn't do the same. + +See: https://github.com/raspberrypi/linux/issues/5748 + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -667,7 +667,7 @@ static int dw_configure_dai_by_dt(struct + if (WARN_ON(idx >= ARRAY_SIZE(bus_widths))) + return -EINVAL; + +- ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_192000); ++ ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_384000); + if (ret < 0) + return ret; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1176-ASoC-dwc-Fix-full-duplex-mode.patch b/target/linux/bcm27xx/patches-6.1/950-1176-ASoC-dwc-Fix-full-duplex-mode.patch new file mode 100644 index 0000000000..f4b7098fae --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1176-ASoC-dwc-Fix-full-duplex-mode.patch @@ -0,0 +1,63 @@ +From cbc65d9c95088d1437a5a84c7d6628b8d27a86f1 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 28 Nov 2023 12:14:03 +0000 +Subject: [PATCH] ASoC: dwc: Fix full-duplex mode + +Configuration of the DMA register was carelessly zeroing bits that may +used by a stream in the other direction. Preserve them instead. + +See: https://github.com/raspberrypi/linux/issues/5741 + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -189,10 +189,17 @@ static void dw_i2s_config(struct dw_i2s_ + { + struct i2s_clk_config_data *config = &dev->config; + u32 ch_reg; +- u32 dmacr = 0; ++ u32 dmacr; + + i2s_disable_channels(dev, stream); + ++ dmacr = i2s_read_reg(dev->i2s_base, DMACR); ++ ++ if (stream == SNDRV_PCM_STREAM_PLAYBACK) ++ dmacr &= ~(DMACR_DMAEN_TXCH0 * 0xf); ++ else ++ dmacr &= ~(DMACR_DMAEN_RXCH0 * 0xf); ++ + for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_write_reg(dev->i2s_base, TCR(ch_reg), +@@ -210,10 +217,6 @@ static void dw_i2s_config(struct dw_i2s_ + dmacr |= (DMACR_DMAEN_RXCH0 << ch_reg); + } + } +- if (stream == SNDRV_PCM_STREAM_PLAYBACK) +- dmacr |= DMACR_DMAEN_TX; +- else if (stream == SNDRV_PCM_STREAM_CAPTURE) +- dmacr |= DMACR_DMAEN_RX; + + i2s_write_reg(dev->i2s_base, DMACR, dmacr); + } +@@ -319,10 +322,13 @@ static int dw_i2s_startup(struct snd_pcm + + dw_i2s_config(dev, substream->stream); + dmacr = i2s_read_reg(dev->i2s_base, DMACR); +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_data = &dev->play_dma_data; +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ dmacr |= DMACR_DMAEN_TX; ++ } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + dma_data = &dev->capture_dma_data; ++ dmacr |= DMACR_DMAEN_RX; ++ } + + snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); + i2s_write_reg(dev->i2s_base, DMACR, dmacr); diff --git a/target/linux/bcm27xx/patches-6.1/950-1179-ASoC-pcm512x-Adds-bindings-for-TAS575x-devices.patch b/target/linux/bcm27xx/patches-6.1/950-1179-ASoC-pcm512x-Adds-bindings-for-TAS575x-devices.patch new file mode 100644 index 0000000000..8472c3e9e1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1179-ASoC-pcm512x-Adds-bindings-for-TAS575x-devices.patch @@ -0,0 +1,45 @@ +From a7ac27fbac1aa3fb8316cf1ff6dd2f81109d46d2 Mon Sep 17 00:00:00 2001 +From: Joerg Schambacher +Date: Fri, 29 Sep 2023 17:05:55 +0200 +Subject: [PATCH] ASoC: pcm512x: Adds bindings for TAS575x devices + +commit 736b884a7b68c4eeb66dbf75b97c8ec9b9eeff7f upstream. + +The TAS5754/6 power amplifiers use the same pcm512x driver with +only minor restictions described in the bindings document. + +Signed-off-by: Joerg Schambacher +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20230929150555.405388-1-joerg.hifiberry@gmail.com +Signed-off-by: Mark Brown +--- + Documentation/devicetree/bindings/sound/pcm512x.txt | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/Documentation/devicetree/bindings/sound/pcm512x.txt ++++ b/Documentation/devicetree/bindings/sound/pcm512x.txt +@@ -1,12 +1,12 @@ +-PCM512x audio CODECs ++PCM512x and TAS575x audio CODECs/amplifiers + + These devices support both I2C and SPI (configured with pin strapping +-on the board). ++on the board). The TAS575x devices only support I2C. + + Required properties: + +- - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or +- "ti,pcm5142" ++ - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141", ++ "ti,pcm5142", "ti,tas5754" or "ti,tas5756" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. +@@ -25,6 +25,7 @@ Optional properties: + through <6>. The device will be configured for clock input on the + given pll-in pin and PLL output on the given pll-out pin. An + external connection from the pll-out pin to the SCLK pin is assumed. ++ Caution: the TAS-desvices only support gpios 1,2 and 3 + + Examples: + diff --git a/target/linux/bcm27xx/patches-6.1/950-1180-ASoC-Adds-support-for-TAS575x-to-the-pcm512x-driver.patch b/target/linux/bcm27xx/patches-6.1/950-1180-ASoC-Adds-support-for-TAS575x-to-the-pcm512x-driver.patch new file mode 100644 index 0000000000..5009b225a3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1180-ASoC-Adds-support-for-TAS575x-to-the-pcm512x-driver.patch @@ -0,0 +1,102 @@ +From a535dd07aff73f3a6eb40174ab5dc413d05f36a1 Mon Sep 17 00:00:00 2001 +From: Joerg Schambacher +Date: Fri, 29 Sep 2023 17:07:20 +0200 +Subject: [PATCH] ASoC: Adds support for TAS575x to the pcm512x driver + +commit 1f817805262c2c34142291da376d4932d3c493bc upstream. + +Enables the existing pcm512x driver to control the almost +compatible TAS5754 and -76 amplifers. Both amplifiers support +only an I2C interface and the internal PLL must be always +on to provide necessary clocks to the amplifier section. +Tested on TAS5756 with support from Andreas Arbesser-Krasser +from Texas Instruments + +Signed-off-by: Joerg Schambacher +Link: https://lore.kernel.org/r/20230929150722.405415-1-joerg.hifiberry@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/codecs/pcm512x-i2c.c | 4 ++++ + sound/soc/codecs/pcm512x.c | 36 +++++++++++++++++++++++++++++++--- + 2 files changed, 37 insertions(+), 3 deletions(-) + +--- a/sound/soc/codecs/pcm512x-i2c.c ++++ b/sound/soc/codecs/pcm512x-i2c.c +@@ -39,6 +39,8 @@ static const struct i2c_device_id pcm512 + { "pcm5122", }, + { "pcm5141", }, + { "pcm5142", }, ++ { "tas5754", }, ++ { "tas5756", }, + { } + }; + MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); +@@ -49,6 +51,8 @@ static const struct of_device_id pcm512x + { .compatible = "ti,pcm5122", }, + { .compatible = "ti,pcm5141", }, + { .compatible = "ti,pcm5142", }, ++ { .compatible = "ti,tas5754", }, ++ { .compatible = "ti,tas5756", }, + { } + }; + MODULE_DEVICE_TABLE(of, pcm512x_of_match); +--- a/sound/soc/codecs/pcm512x.c ++++ b/sound/soc/codecs/pcm512x.c +@@ -48,6 +48,7 @@ struct pcm512x_priv { + int mute; + struct mutex mutex; + unsigned int bclk_ratio; ++ int force_pll_on; + }; + + /* +@@ -1258,10 +1259,34 @@ static int pcm512x_hw_params(struct snd_ + return ret; + } + +- ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, +- PCM512x_PLLE, 0); ++ if (!pcm512x->force_pll_on) { ++ ret = regmap_update_bits(pcm512x->regmap, ++ PCM512x_PLL_EN, PCM512x_PLLE, 0); ++ } else { ++ /* provide minimum PLL config for TAS575x clocking ++ * and leave PLL enabled ++ */ ++ ret = regmap_write(pcm512x->regmap, ++ PCM512x_PLL_COEFF_0, 0x01); ++ if (ret != 0) { ++ dev_err(component->dev, ++ "Failed to set pll coefficient: %d\n", ret); ++ return ret; ++ } ++ ret = regmap_write(pcm512x->regmap, ++ PCM512x_PLL_COEFF_1, 0x04); ++ if (ret != 0) { ++ dev_err(component->dev, ++ "Failed to set pll coefficient: %d\n", ret); ++ return ret; ++ } ++ ret = regmap_write(pcm512x->regmap, ++ PCM512x_PLL_EN, 0x01); ++ dev_dbg(component->dev, "Enabling PLL for TAS575x\n"); ++ } ++ + if (ret != 0) { +- dev_err(component->dev, "Failed to disable pll: %d\n", ret); ++ dev_err(component->dev, "Failed to set pll mode: %d\n", ret); + return ret; + } + } +@@ -1659,6 +1684,11 @@ int pcm512x_probe(struct device *dev, st + ret = -EINVAL; + goto err_pm; + } ++ ++ if (!strcmp(np->name, "tas5756") || ++ !strcmp(np->name, "tas5754")) ++ pcm512x->force_pll_on = 1; ++ dev_dbg(dev, "Device ID: %s\n", np->name); + } + #endif + diff --git a/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch b/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch new file mode 100644 index 0000000000..d914ab6d04 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch @@ -0,0 +1,176 @@ +From 0a0084b8621682ad96d001e798aa239b11a3cf00 Mon Sep 17 00:00:00 2001 +From: Timon Skerutsch +Date: Mon, 13 Nov 2023 22:53:12 +0100 +Subject: [PATCH] drm/panel: add panel-dsi + +Equivalent to panel-dpi for configuring a simple DSI panel with +device tree side timings and bus settings. +Motiviation is the same as for panel-dpi of wanting to support +new simple panels without needing to patch the kernel. + +Signed-off-by: Timon Skerutsch +--- + drivers/gpu/drm/panel/panel-simple.c | 123 ++++++++++++++++++++++++++- + 1 file changed, 122 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/panel/panel-simple.c ++++ b/drivers/gpu/drm/panel/panel-simple.c +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + + /** + * struct panel_desc - Describes a simple panel. +@@ -4660,6 +4661,9 @@ static const struct panel_desc_dsi osd10 + .lanes = 4, + }; + ++// for panels using generic panel-dsi binding ++static struct panel_desc_dsi panel_dsi; ++ + static const struct of_device_id dsi_of_match[] = { + { + .compatible = "auo,b080uan01", +@@ -4683,14 +4687,118 @@ static const struct of_device_id dsi_of_ + .compatible = "osddisplays,osd101t2045-53ts", + .data = &osd101t2045_53ts + }, { ++ /* Must be the last entry */ ++ .compatible = "panel-dsi", ++ .data = &panel_dsi, ++ }, { + /* sentinel */ + } + }; + MODULE_DEVICE_TABLE(of, dsi_of_match); + ++ ++/* Checks for DSI panel definition in device-tree, analog to panel_dpi */ ++static int panel_dsi_dt_probe(struct device *dev, ++ struct panel_desc_dsi *desc_dsi) ++{ ++ struct panel_desc *desc; ++ struct display_timing *timing; ++ const struct device_node *np; ++ const char *dsi_color_format; ++ const char *dsi_mode_flags; ++ struct property *prop; ++ int dsi_lanes, ret; ++ ++ np = dev->of_node; ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL); ++ if (!timing) ++ return -ENOMEM; ++ ++ ret = of_get_display_timing(np, "panel-timing", timing); ++ if (ret < 0) { ++ dev_err(dev, "%pOF: no panel-timing node found for \"panel-dsi\" binding\n", ++ np); ++ return ret; ++ } ++ ++ desc->timings = timing; ++ desc->num_timings = 1; ++ ++ of_property_read_u32(np, "width-mm", &desc->size.width); ++ of_property_read_u32(np, "height-mm", &desc->size.height); ++ ++ dsi_lanes = drm_of_get_data_lanes_count_ep(np, 0, 0, 1, 4); ++ ++ if (dsi_lanes < 0) { ++ dev_err(dev, "%pOF: no or too many data-lanes defined", np); ++ return dsi_lanes; ++ } ++ ++ desc_dsi->lanes = dsi_lanes; ++ ++ of_property_read_string(np, "dsi-color-format", &dsi_color_format); ++ if (!strcmp(dsi_color_format, "RGB888")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB888; ++ desc->bpc = 8; ++ } else if (!strcmp(dsi_color_format, "RGB565")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB565; ++ desc->bpc = 6; ++ } else if (!strcmp(dsi_color_format, "RGB666")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB666; ++ desc->bpc = 6; ++ } else if (!strcmp(dsi_color_format, "RGB666_PACKED")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB666_PACKED; ++ desc->bpc = 6; ++ } else { ++ dev_err(dev, "%pOF: no valid dsi-color-format defined", np); ++ return -EINVAL; ++ } ++ ++ ++ of_property_for_each_string(np, "mode", prop, dsi_mode_flags) { ++ if (!strcmp(dsi_mode_flags, "MODE_VIDEO")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_BURST")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_BURST; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_SYNC_PULSE")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_AUTO_VERT")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_AUTO_VERT; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_HSE")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_HSE; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HFP")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HFP; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HBP")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HBP; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HSA")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HSA; ++ else if (!strcmp(dsi_mode_flags, "MODE_VSYNC_FLUSH")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VSYNC_FLUSH; ++ else if (!strcmp(dsi_mode_flags, "MODE_NO_EOT_PACKET")) ++ desc_dsi->flags |= MIPI_DSI_MODE_NO_EOT_PACKET; ++ else if (!strcmp(dsi_mode_flags, "CLOCK_NON_CONTINUOUS")) ++ desc_dsi->flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS; ++ else if (!strcmp(dsi_mode_flags, "MODE_LPM")) ++ desc_dsi->flags |= MIPI_DSI_MODE_LPM; ++ else if (!strcmp(dsi_mode_flags, "HS_PKT_END_ALIGNED")) ++ desc_dsi->flags |= MIPI_DSI_HS_PKT_END_ALIGNED; ++ } ++ ++ desc->connector_type = DRM_MODE_CONNECTOR_DSI; ++ desc_dsi->desc = *desc; ++ ++ return 0; ++} ++ + static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) + { + const struct panel_desc_dsi *desc; ++ struct panel_desc_dsi *dt_desc; + const struct of_device_id *id; + int err; + +@@ -4698,7 +4806,20 @@ static int panel_simple_dsi_probe(struct + if (!id) + return -ENODEV; + +- desc = id->data; ++ if (id->data == &panel_dsi) { ++ /* Handle the generic panel-dsi binding */ ++ dt_desc = devm_kzalloc(&dsi->dev, sizeof(*dt_desc), GFP_KERNEL); ++ if (!dt_desc) ++ return -ENOMEM; ++ ++ err = panel_dsi_dt_probe(&dsi->dev, dt_desc); ++ if (err < 0) ++ return err; ++ ++ desc = dt_desc; ++ } else { ++ desc = id->data; ++ } + + err = panel_simple_probe(&dsi->dev, &desc->desc); + if (err < 0) diff --git a/target/linux/bcm27xx/patches-6.1/950-1183-dt-bindings-display-panel-dsi-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-1183-dt-bindings-display-panel-dsi-bindings.patch new file mode 100644 index 0000000000..c75ca8e8ac --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1183-dt-bindings-display-panel-dsi-bindings.patch @@ -0,0 +1,136 @@ +From e14ceeadfa5b9d8a41e73edfa416bbe92dd5b20d Mon Sep 17 00:00:00 2001 +From: Timon Skerutsch +Date: Mon, 13 Nov 2023 22:53:22 +0100 +Subject: [PATCH] dt-bindings: display: panel-dsi bindings + +Bindings for the panel-dsi specific additions to panel-simple. +Allow for DSI specific bus settings and panel timing +to be define in devicetree. Very similar to panel-dpi. + +Signed-off-by: Timon Skerutsch +--- + .../bindings/display/panel/panel-dsi.yaml | 118 ++++++++++++++++++ + 1 file changed, 118 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/panel/panel-dsi.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/panel/panel-dsi.yaml +@@ -0,0 +1,118 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/panel/panel-dsi.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Generic MIPI DSI Panel ++ ++maintainers: ++ - Timon Skerutsch ++ ++allOf: ++ - $ref: panel-common.yaml# ++ ++properties: ++ compatible: ++ description: ++ Shall contain a panel specific compatible and "panel-dsi" ++ in that order. ++ items: ++ - {} ++ - const: panel-dsi ++ ++ dsi-color-format: ++ description: | ++ The color format used by the panel. Only DSI supported formats are allowed. ++ enum: ++ - RGB888 ++ - RGB666 ++ - RGB666_PACKED ++ - RGB565 ++ ++ port: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ unevaluatedProperties: false ++ description: ++ Panel MIPI DSI input ++ ++ properties: ++ endpoint: ++ $ref: /schemas/media/video-interfaces.yaml# ++ unevaluatedProperties: false ++ ++ properties: ++ data-lanes: true ++ ++ required: ++ - data-lanes ++ ++ mode: ++ description: | ++ DSI mode flags. See DSI Specs for details. ++ These are driver independent features of the DSI bus. ++ items: ++ - const: MODE_VIDEO ++ - const: MODE_VIDEO_BURST ++ - const: MODE_VIDEO_SYNC_PULSE ++ - const: MODE_VIDEO_AUTO_VERT ++ - const: MODE_VIDEO_HSE ++ - const: MODE_VIDEO_NO_HFP ++ - const: MODE_VIDEO_NO_HBP ++ - const: MODE_VIDEO_NO_HSA ++ - const: MODE_VSYNC_FLUSH ++ - const: MODE_NO_EOT_PACKET ++ - const: CLOCK_NON_CONTINUOUS ++ - const: MODE_LPM ++ - const: HS_PKT_END_ALIGNED ++ ++ reg: true ++ backlight: true ++ enable-gpios: true ++ width-mm: true ++ height-mm: true ++ panel-timing: true ++ power-supply: true ++ reset-gpios: true ++ ddc-i2c-bus: true ++ ++required: ++ - panel-timing ++ - reg ++ - power-supply ++ - dsi-color-format ++ - port ++ ++additionalProperties: false ++ ++examples: ++ - | ++ panel { ++ compatible = "panel-mfgr,generic-dsi-panel","panel-dsi"; ++ power-supply = <&vcc_supply>; ++ backlight = <&backlight>; ++ dsi-color-format = "RGB888"; ++ reg = <0>; ++ mode = "MODE_VIDEO", "MODE_VIDEO_BURST", "MODE_NO_EOT_PACKET"; ++ ++ port { ++ panel_dsi_port: endpoint { ++ data-lanes = <1 2>; ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ ++ panel-timing { ++ clock-frequency = <9200000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <8>; ++ hback-porch = <4>; ++ hsync-len = <41>; ++ vback-porch = <2>; ++ vfront-porch = <4>; ++ vsync-len = <10>; ++ }; ++ }; ++ ++... diff --git a/target/linux/bcm27xx/patches-6.1/950-1184-overlays-example-overlay-for-using-panel-dsi-on-RPi.patch b/target/linux/bcm27xx/patches-6.1/950-1184-overlays-example-overlay-for-using-panel-dsi-on-RPi.patch new file mode 100644 index 0000000000..28a82d596d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1184-overlays-example-overlay-for-using-panel-dsi-on-RPi.patch @@ -0,0 +1,176 @@ +From ccf75f2a6f4045484c4539f7d47264f8f6b8453c Mon Sep 17 00:00:00 2001 +From: Timon Skerutsch +Date: Mon, 13 Nov 2023 22:52:35 +0100 +Subject: [PATCH] overlays: example overlay for using panel-dsi on RPi + +Analog to the generic panel-dpi overlay to use panel-dsi with dtparam +to not require a panel specific overlay for simple use cases that +do not require setting more niche DSI modes. + +Signed-off-by: Timon Skerutsch +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 31 +++++ + .../overlays/vc4-kms-dsi-generic-overlay.dts | 106 ++++++++++++++++++ + 3 files changed, 138 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dsi-generic-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -293,6 +293,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + vc4-kms-dpi-hyperpixel4sq.dtbo \ + vc4-kms-dpi-panel.dtbo \ + vc4-kms-dsi-7inch.dtbo \ ++ vc4-kms-dsi-generic.dtbo \ + vc4-kms-dsi-lt070me05000.dtbo \ + vc4-kms-dsi-lt070me05000-v2.dtbo \ + vc4-kms-dsi-waveshare-panel.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -4785,6 +4785,37 @@ Params: sizex Touchscr + the default DSI1 and i2c_csi_dsi). + + ++Name: vc4-kms-dsi-generic ++Info: Enable a generic DSI display under KMS. ++ Default timings are for a 840x480 RGB888 panel. ++ Requires vc4-kms-v3d to be loaded. ++Load: dtoverlay=vc4-kms-dsi-generic,= ++Params: clock-frequency Display clock frequency (Hz) ++ hactive Horizontal active pixels ++ hfp Horizontal front porch ++ hsync Horizontal sync pulse width ++ hbp Horizontal back porch ++ vactive Vertical active lines ++ vfp Vertical front porch ++ vsync Vertical sync pulse width ++ vbp Vertical back porch ++ width-mm Define the screen width in mm ++ height-mm Define the screen height in mm ++ rgb565 Change to RGB565 output ++ rgb666 Change to RGB666 output ++ rgb666p Change to RGB666 output with pixel packing ++ rgb888 Change to RGB888 output, this is the default ++ one-lane Use one DSI lane for data transmission ++ This is the default ++ two-lane Use two DSI lanes for data transmission ++ three-lane Use three DSI lanes for data transmission ++ Only supported on Pi5 and CM ++ four-lane Use four DSI lanes for data transmission ++ Only supported on Pi5 and CM ++ dsi0 Switch DSI port to DSI0 ++ Only supported on Pi5 and CM ++ ++ + Name: vc4-kms-dsi-lt070me05000 + Info: Enable a JDI LT070ME05000 DSI display on DSI1. + Note that this is a 4 lane DSI device, so it will only work on a Compute +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-generic-overlay.dts +@@ -0,0 +1,106 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ dsi_frag: fragment@0 { ++ target = <&dsi1>; ++ __overlay__{ ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port { ++ dsi_out:endpoint { ++ remote-endpoint = <&panel_dsi_port>; ++ }; ++ }; ++ panel: panel-dsi-generic@0 { ++ // See panel-dsi.yaml binding ++ // Using dummy name for panel model ++ compatible = "Generic,panel-dsi","panel-dsi"; ++ reg = <0>; ++ power-supply = <0>; ++ backlight = <0>; ++ dsi-color-format = "RGB888"; ++ mode = "MODE_VIDEO"; ++ width-mm = <0>; ++ height-mm = <0>; ++ ++ port { ++ panel_dsi_port: endpoint { ++ data-lanes = <1>; ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ ++ timing: panel-timing { ++ clock-frequency = <30000000>; ++ hactive = <840>; ++ vactive = <480>; ++ hback-porch = <44>; ++ hfront-porch = <46>; ++ hsync-len = <2>; ++ vback-porch = <18>; ++ vfront-porch = <16>; ++ vsync-len = <2>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1 2>; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1 2 3>; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ ++ __overrides__ { ++ dsi0 = <&dsi_frag>, "target:0=",<&dsi0>; ++ ++ clock-frequency = <&timing>, "clock-frequency:0"; ++ hactive = <&timing>, "hactive:0"; ++ hfp = <&timing>, "hfront-porch:0"; ++ hsync = <&timing>, "hsync-len:0"; ++ hbp = <&timing>, "hback-porch:0"; ++ vactive = <&timing>, "vactive:0"; ++ vfp = <&timing>, "vfront-porch:0"; ++ vsync = <&timing>, "vsync-len:0"; ++ vbp = <&timing>, "vback-porch:0"; ++ ++ width-mm = <&panel>, "width-mm:0"; ++ height-mm = <&panel>, "height-mm:0"; ++ ++ rgb565 = <&panel>, "dsi-color-format=RGB565"; ++ rgb666p = <&panel>, "dsi-color-format=RGB666_PACKED"; ++ rgb666 = <&panel>, "dsi-color-format=RGB666"; ++ rgb888 = <&panel>, "dsi-color-format=RGB888"; ++ one-lane = <0>,"+1"; ++ two-lane = <0>,"+2"; ++ three-lane = <0>,"+3"; ++ four-lane = <0>,"+4"; ++ }; ++ ++}; diff --git a/target/linux/bcm27xx/patches-6.1/950-1185-overlays-ADS1115-allow-specification-of-the-i2c-bus.patch b/target/linux/bcm27xx/patches-6.1/950-1185-overlays-ADS1115-allow-specification-of-the-i2c-bus.patch new file mode 100644 index 0000000000..ef9328bd6f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1185-overlays-ADS1115-allow-specification-of-the-i2c-bus.patch @@ -0,0 +1,159 @@ +From a477a6351575aa173f9f82857f5797e384fbc704 Mon Sep 17 00:00:00 2001 +From: JinShil +Date: Tue, 28 Nov 2023 17:05:44 +0900 +Subject: [PATCH] overlays: ADS1115: allow specification of the i2c bus + +--- + arch/arm/boot/dts/overlays/README | 10 +++ + .../arm/boot/dts/overlays/ads1115-overlay.dts | 80 +++++++++++++------ + 2 files changed, 66 insertions(+), 24 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -489,6 +489,16 @@ Params: addr I2C bus + cha_gain Set the gain of the Programmable Gain + Amplifier for this channel. (Default 1 sets the + full scale of the channel to 4.096 Volts) ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c3 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c4 Choose the I2C4 bus (configure with the i2c4 ++ overlay - BCM2711 only) ++ i2c5 Choose the I2C5 bus (configure with the i2c5 ++ overlay - BCM2711 only) ++ i2c6 Choose the I2C6 bus (configure with the i2c6 ++ overlay - BCM2711 only) + + Channel parameters can be set for each enabled channel. + A maximum of 4 channels can be enabled (letters a thru d). +--- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts +@@ -9,23 +9,6 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2c_arm>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- +- ads1115: ads1115@48 { +- compatible = "ti,ads1115"; +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- reg = <0x48>; +- }; +- }; +- }; +- +- fragment@1 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -39,7 +22,7 @@ + }; + }; + +- fragment@2 { ++ fragment@1 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -53,7 +36,7 @@ + }; + }; + +- fragment@3 { ++ fragment@2 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -67,7 +50,7 @@ + }; + }; + +- fragment@4 { ++ fragment@3 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -81,23 +64,72 @@ + }; + }; + ++ fragment@4 { ++ target = <&i2cbus>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ads1115: ads1115@48 { ++ compatible = "ti,ads1115"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x48>; ++ }; ++ }; ++ }; ++ ++ frag100: fragment@100 { ++ target = <&i2c1>; ++ i2cbus: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@102 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + addr = <&ads1115>,"reg:0"; +- cha_enable = <0>,"=1"; ++ cha_enable = <0>,"=0"; + cha_cfg = <&channel_a>,"reg:0"; + cha_gain = <&channel_a>,"ti,gain:0"; + cha_datarate = <&channel_a>,"ti,datarate:0"; +- chb_enable = <0>,"=2"; ++ chb_enable = <0>,"=1"; + chb_cfg = <&channel_b>,"reg:0"; + chb_gain = <&channel_b>,"ti,gain:0"; + chb_datarate = <&channel_b>,"ti,datarate:0"; +- chc_enable = <0>,"=3"; ++ chc_enable = <0>,"=2"; + chc_cfg = <&channel_c>,"reg:0"; + chc_gain = <&channel_c>,"ti,gain:0"; + chc_datarate = <&channel_c>,"ti,datarate:0"; +- chd_enable = <0>,"=4"; ++ chd_enable = <0>,"=3"; + chd_cfg = <&channel_d>,"reg:0"; + chd_gain = <&channel_d>,"ti,gain:0"; + chd_datarate = <&channel_d>,"ti,datarate:0"; ++ i2c0 = <&frag100>, "target:0=",<&i2c0>; ++ i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+101+102"; ++ i2c3 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c3"; ++ i2c4 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c4"; ++ i2c5 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c5"; ++ i2c6 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c6"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1186-dts-bcm2712-put-usb-under-axi-not-soc.patch b/target/linux/bcm27xx/patches-6.1/950-1186-dts-bcm2712-put-usb-under-axi-not-soc.patch new file mode 100644 index 0000000000..b66265f5a1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1186-dts-bcm2712-put-usb-under-axi-not-soc.patch @@ -0,0 +1,59 @@ +From 82069a7a02632aa60fa5c69415bf891ede7d6fd4 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Tue, 5 Dec 2023 16:55:17 +0000 +Subject: [PATCH] dts: bcm2712: put usb under /axi not /soc + +On 2712, the DWC USB controller is no longer attached to the Videocore +30-bit bus with its associated aliases, and can see the bottom 4GB of +RAM directly. + +Ideally it should make use of IOMMU6 but for now software bounce buffers +get it working. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/bcm2712.dtsi | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -133,19 +133,6 @@ + status = "disabled"; + }; + +- usb: usb@7c480000 { +- compatible = "brcm,bcm2835-usb"; +- reg = <0x7c480000 0x10000>; +- interrupts = ; +- #address-cells = <1>; +- #size-cells = <0>; +- clocks = <&clk_usb>; +- clock-names = "otg"; +- phys = <&usbphy>; +- phy-names = "usb2-phy"; +- status = "disabled"; +- }; +- + mop: mop@7c500000 { + compatible = "brcm,bcm2712-mop"; + reg = <0x7c500000 0x20>; +@@ -1145,6 +1132,19 @@ + 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 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1187-drm-vc4-Correct-HVS-muxing-setup-for-the-moplet.patch b/target/linux/bcm27xx/patches-6.1/950-1187-drm-vc4-Correct-HVS-muxing-setup-for-the-moplet.patch new file mode 100644 index 0000000000..be02fd27fa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1187-drm-vc4-Correct-HVS-muxing-setup-for-the-moplet.patch @@ -0,0 +1,26 @@ +From 01139e4e9141d031c6f4f00371e5eb52fa78839e Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 5 Dec 2023 18:28:19 +0000 +Subject: [PATCH] drm/vc4: Correct HVS muxing setup for the moplet + +The moplet registers as VC4_ENCODER_TYPE_TXP1 and can be +fed from mux output 2 of HVS channel 1. + +Correct the option which checked for VC4_ENCODER_TYPE_TXP0 + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_kms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -365,7 +365,7 @@ static void vc6_hvs_pv_muxing_commit(str + mux = 0; + break; + +- case VC4_ENCODER_TYPE_TXP0: ++ case VC4_ENCODER_TYPE_TXP1: + mux = 2; + break; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1188-drm-vc4-Mop-and-moplet-have-different-register-offse.patch b/target/linux/bcm27xx/patches-6.1/950-1188-drm-vc4-Mop-and-moplet-have-different-register-offse.patch new file mode 100644 index 0000000000..f1bb26a26b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1188-drm-vc4-Mop-and-moplet-have-different-register-offse.patch @@ -0,0 +1,68 @@ +From cc948130d3e1c70ef21ae9963b56e0d500cef70b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 5 Dec 2023 18:29:34 +0000 +Subject: [PATCH] drm/vc4: Mop and moplet have different register offsets for + high addr + +MOP uses register offset 0x24 for the high bits of the address, +whilst Moplet uses 0x1c. + +Handle this difference between the block types. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 8 ++++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -564,6 +564,7 @@ struct vc4_crtc_data { + struct vc4_txp_data { + struct vc4_crtc_data base; + enum vc4_encoder_type encoder_type; ++ unsigned int high_addr_ptr_reg; + unsigned int has_byte_enable:1; + unsigned int size_minus_one:1; + unsigned int supports_40bit_addresses:1; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -145,7 +145,8 @@ + /* Number of lines received and committed to memory. */ + #define TXP_PROGRESS 0x10 + +-#define TXP_DST_PTR_HIGH 0x1c ++#define TXP_DST_PTR_HIGH_MOPLET 0x1c ++#define TXP_DST_PTR_HIGH_MOP 0x24 + + #define TXP_READ(offset) \ + ({ \ +@@ -338,10 +339,11 @@ static void vc4_txp_connector_atomic_com + + gem = drm_fb_dma_get_gem_obj(fb, 0); + addr = gem->dma_addr + fb->offsets[0]; ++ + TXP_WRITE(TXP_DST_PTR, lower_32_bits(addr)); + + if (txp_data->supports_40bit_addresses) +- TXP_WRITE(TXP_DST_PTR_HIGH, upper_32_bits(addr) & 0xff); ++ TXP_WRITE(txp_data->high_addr_ptr_reg, upper_32_bits(addr) & 0xff); + + TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); + +@@ -520,6 +522,7 @@ const struct vc4_txp_data bcm2712_mop_da + .hvs_output = 2, + }, + .encoder_type = VC4_ENCODER_TYPE_TXP0, ++ .high_addr_ptr_reg = TXP_DST_PTR_HIGH_MOP, + .has_byte_enable = true, + .size_minus_one = true, + .supports_40bit_addresses = true, +@@ -533,6 +536,7 @@ const struct vc4_txp_data bcm2712_moplet + .hvs_output = 4, + }, + .encoder_type = VC4_ENCODER_TYPE_TXP1, ++ .high_addr_ptr_reg = TXP_DST_PTR_HIGH_MOPLET, + .size_minus_one = true, + .supports_40bit_addresses = true, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1189-arm-dt-bcm2712-Correct-the-size-of-the-register-rang.patch b/target/linux/bcm27xx/patches-6.1/950-1189-arm-dt-bcm2712-Correct-the-size-of-the-register-rang.patch new file mode 100644 index 0000000000..ece5c716e7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1189-arm-dt-bcm2712-Correct-the-size-of-the-register-rang.patch @@ -0,0 +1,25 @@ +From 36593e2e27769d635ef18301f25b5e219a23949a Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 5 Dec 2023 18:31:25 +0000 +Subject: [PATCH] arm: dt: bcm2712: Correct the size of the register range for + MOP + +The Mop covers 0x28 bytes of registers, so ensure the range is +defined appropriately. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -135,7 +135,7 @@ + + mop: mop@7c500000 { + compatible = "brcm,bcm2712-mop"; +- reg = <0x7c500000 0x20>; ++ reg = <0x7c500000 0x28>; + interrupt-parent = <&disp_intr>; + interrupts = <1>; + status = "disabled"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1192-media-Add-MIPI-CCI-register-access-helper-functions.patch b/target/linux/bcm27xx/patches-6.1/950-1192-media-Add-MIPI-CCI-register-access-helper-functions.patch new file mode 100644 index 0000000000..3305e66986 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1192-media-Add-MIPI-CCI-register-access-helper-functions.patch @@ -0,0 +1,388 @@ +From ae0e1b70f675f6ac7966e427f0d8f57812dbc312 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 27 Jun 2023 14:51:04 +0200 +Subject: [PATCH] media: Add MIPI CCI register access helper functions + +The CSI2 specification specifies a standard method to access camera sensor +registers called "Camera Control Interface (CCI)". + +This uses either 8 or 16 bit (big-endian wire order) register addresses +and supports 8, 16, 24 or 32 bit (big-endian wire order) register widths. + +Currently a lot of Linux camera sensor drivers all have their own custom +helpers for this, often copy and pasted from other drivers. + +Add a set of generic helpers for this so that all sensor drivers can +switch to a single common implementation. + +These helpers take an extra optional "int *err" function parameter, +this can be used to chain a bunch of register accesses together with +only a single error check at the end, rather than needing to error +check each individual register access. The first failing call will +set the contents of err to a non 0 value and all other calls will +then become no-ops. + +Link: https://lore.kernel.org/linux-media/59aefa7f-7bf9-6736-6040-39551329cd0a@redhat.com/ + +Reviewed-by: Andy Shevchenko +Tested-by: Tommaso Merciai +Reviewed-by: Tommaso Merciai +Signed-off-by: Hans de Goede +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 613cbb91e9cee7cf5a61f0816d2acab7bc117407) +--- + Documentation/driver-api/media/v4l2-cci.rst | 5 + + Documentation/driver-api/media/v4l2-core.rst | 1 + + drivers/media/v4l2-core/Kconfig | 9 + + drivers/media/v4l2-core/Makefile | 1 + + drivers/media/v4l2-core/v4l2-cci.c | 166 +++++++++++++++++++ + include/media/v4l2-cci.h | 125 ++++++++++++++ + 6 files changed, 307 insertions(+) + create mode 100644 Documentation/driver-api/media/v4l2-cci.rst + create mode 100644 drivers/media/v4l2-core/v4l2-cci.c + create mode 100644 include/media/v4l2-cci.h + +--- /dev/null ++++ b/Documentation/driver-api/media/v4l2-cci.rst +@@ -0,0 +1,5 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++V4L2 CCI kAPI ++^^^^^^^^^^^^^ ++.. kernel-doc:: include/media/v4l2-cci.h +--- a/Documentation/driver-api/media/v4l2-core.rst ++++ b/Documentation/driver-api/media/v4l2-core.rst +@@ -22,6 +22,7 @@ Video4Linux devices + v4l2-mem2mem + v4l2-async + v4l2-fwnode ++ v4l2-cci + v4l2-rect + v4l2-tuner + v4l2-common +--- a/drivers/media/v4l2-core/Kconfig ++++ b/drivers/media/v4l2-core/Kconfig +@@ -74,6 +74,15 @@ config V4L2_FWNODE + config V4L2_ASYNC + tristate + ++config V4L2_CCI ++ tristate ++ ++config V4L2_CCI_I2C ++ tristate ++ depends on I2C ++ select REGMAP_I2C ++ select V4L2_CCI ++ + # Used by drivers that need Videobuf modules + config VIDEOBUF_GEN + tristate +--- a/drivers/media/v4l2-core/Makefile ++++ b/drivers/media/v4l2-core/Makefile +@@ -25,6 +25,7 @@ videodev-$(CONFIG_VIDEO_V4L2_I2C) += v4l + # (e. g. LC_ALL=C sort Makefile) + + obj-$(CONFIG_V4L2_ASYNC) += v4l2-async.o ++obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o + obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o + obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o + obj-$(CONFIG_V4L2_H264) += v4l2-h264.o +--- /dev/null ++++ b/drivers/media/v4l2-core/v4l2-cci.c +@@ -0,0 +1,166 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * MIPI Camera Control Interface (CCI) register access helpers. ++ * ++ * Copyright (C) 2023 Hans de Goede ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) ++{ ++ unsigned int len; ++ u8 buf[8]; ++ int ret; ++ ++ if (err && *err) ++ return *err; ++ ++ len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); ++ reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); ++ ++ ret = regmap_bulk_read(map, reg, buf, len); ++ if (ret) { ++ dev_err(regmap_get_device(map), "Error reading reg 0x%4x: %d\n", ++ reg, ret); ++ goto out; ++ } ++ ++ switch (len) { ++ case 1: ++ *val = buf[0]; ++ break; ++ case 2: ++ *val = get_unaligned_be16(buf); ++ break; ++ case 3: ++ *val = get_unaligned_be24(buf); ++ break; ++ case 4: ++ *val = get_unaligned_be32(buf); ++ break; ++ case 8: ++ *val = get_unaligned_be64(buf); ++ break; ++ default: ++ dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", ++ len, reg); ++ ret = -EINVAL; ++ break; ++ } ++ ++out: ++ if (ret && err) ++ *err = ret; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cci_read); ++ ++int cci_write(struct regmap *map, u32 reg, u64 val, int *err) ++{ ++ unsigned int len; ++ u8 buf[8]; ++ int ret; ++ ++ if (err && *err) ++ return *err; ++ ++ len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); ++ reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); ++ ++ switch (len) { ++ case 1: ++ buf[0] = val; ++ break; ++ case 2: ++ put_unaligned_be16(val, buf); ++ break; ++ case 3: ++ put_unaligned_be24(val, buf); ++ break; ++ case 4: ++ put_unaligned_be32(val, buf); ++ break; ++ case 8: ++ put_unaligned_be64(val, buf); ++ break; ++ default: ++ dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", ++ len, reg); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ret = regmap_bulk_write(map, reg, buf, len); ++ if (ret) ++ dev_err(regmap_get_device(map), "Error writing reg 0x%4x: %d\n", ++ reg, ret); ++ ++out: ++ if (ret && err) ++ *err = ret; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cci_write); ++ ++int cci_update_bits(struct regmap *map, u32 reg, u64 mask, u64 val, int *err) ++{ ++ u64 readval; ++ int ret; ++ ++ ret = cci_read(map, reg, &readval, err); ++ if (ret) ++ return ret; ++ ++ val = (readval & ~mask) | (val & mask); ++ ++ return cci_write(map, reg, val, err); ++} ++EXPORT_SYMBOL_GPL(cci_update_bits); ++ ++int cci_multi_reg_write(struct regmap *map, const struct cci_reg_sequence *regs, ++ unsigned int num_regs, int *err) ++{ ++ unsigned int i; ++ int ret; ++ ++ for (i = 0; i < num_regs; i++) { ++ ret = cci_write(map, regs[i].reg, regs[i].val, err); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(cci_multi_reg_write); ++ ++#if IS_ENABLED(CONFIG_V4L2_CCI_I2C) ++struct regmap *devm_cci_regmap_init_i2c(struct i2c_client *client, ++ int reg_addr_bits) ++{ ++ struct regmap_config config = { ++ .reg_bits = reg_addr_bits, ++ .val_bits = 8, ++ .reg_format_endian = REGMAP_ENDIAN_BIG, ++ .disable_locking = true, ++ }; ++ ++ return devm_regmap_init_i2c(client, &config); ++} ++EXPORT_SYMBOL_GPL(devm_cci_regmap_init_i2c); ++#endif ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Hans de Goede "); ++MODULE_DESCRIPTION("MIPI Camera Control Interface (CCI) support"); +--- /dev/null ++++ b/include/media/v4l2-cci.h +@@ -0,0 +1,125 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * MIPI Camera Control Interface (CCI) register access helpers. ++ * ++ * Copyright (C) 2023 Hans de Goede ++ */ ++#ifndef _V4L2_CCI_H ++#define _V4L2_CCI_H ++ ++#include ++ ++struct i2c_client; ++struct regmap; ++ ++/** ++ * struct cci_reg_sequence - An individual write from a sequence of CCI writes ++ * ++ * @reg: Register address, use CCI_REG#() macros to encode reg width ++ * @val: Register value ++ * ++ * Register/value pairs for sequences of writes. ++ */ ++struct cci_reg_sequence { ++ u32 reg; ++ u64 val; ++}; ++ ++/* ++ * Macros to define register address with the register width encoded ++ * into the higher bits. ++ */ ++#define CCI_REG_ADDR_MASK GENMASK(15, 0) ++#define CCI_REG_WIDTH_SHIFT 16 ++#define CCI_REG_WIDTH_MASK GENMASK(19, 16) ++ ++#define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) ++ ++/** ++ * cci_read() - Read a value from a single CCI register ++ * ++ * @map: Register map to read from ++ * @reg: Register address to read, use CCI_REG#() macros to encode reg width ++ * @val: Pointer to store read value ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the read will be skipped ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_read(struct regmap *map, u32 reg, u64 *val, int *err); ++ ++/** ++ * cci_write() - Write a value to a single CCI register ++ * ++ * @map: Register map to write to ++ * @reg: Register address to write, use CCI_REG#() macros to encode reg width ++ * @val: Value to be written ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the write will be skipped ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_write(struct regmap *map, u32 reg, u64 val, int *err); ++ ++/** ++ * cci_update_bits() - Perform a read/modify/write cycle on ++ * a single CCI register ++ * ++ * @map: Register map to update ++ * @reg: Register address to update, use CCI_REG#() macros to encode reg width ++ * @mask: Bitmask to change ++ * @val: New value for bitmask ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the update will be skipped ++ * ++ * Note this uses read-modify-write to update the bits, atomicity with regards ++ * to other cci_*() register access functions is NOT guaranteed. ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_update_bits(struct regmap *map, u32 reg, u64 mask, u64 val, int *err); ++ ++/** ++ * cci_multi_reg_write() - Write multiple registers to the device ++ * ++ * @map: Register map to write to ++ * @regs: Array of structures containing register-address, -value pairs to be ++ * written, register-addresses use CCI_REG#() macros to encode reg width ++ * @num_regs: Number of registers to write ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the write will be skipped ++ * ++ * Write multiple registers to the device where the set of register, value ++ * pairs are supplied in any order, possibly not all in a single range. ++ * ++ * Use of the CCI_REG#() macros to encode reg width is mandatory. ++ * ++ * For raw lists of register-address, -value pairs with only 8 bit ++ * wide writes regmap_multi_reg_write() can be used instead. ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_multi_reg_write(struct regmap *map, const struct cci_reg_sequence *regs, ++ unsigned int num_regs, int *err); ++ ++#if IS_ENABLED(CONFIG_V4L2_CCI_I2C) ++/** ++ * devm_cci_regmap_init_i2c() - Create regmap to use with cci_*() register ++ * access functions ++ * ++ * @client: i2c_client to create the regmap for ++ * @reg_addr_bits: register address width to use (8 or 16) ++ * ++ * Note the memory for the created regmap is devm() managed, tied to the client. ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++struct regmap *devm_cci_regmap_init_i2c(struct i2c_client *client, ++ int reg_addr_bits); ++#endif ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-1193-media-dt-bindings-Add-OmniVision-OV64A40.patch b/target/linux/bcm27xx/patches-6.1/950-1193-media-dt-bindings-Add-OmniVision-OV64A40.patch new file mode 100644 index 0000000000..649e8bc393 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1193-media-dt-bindings-Add-OmniVision-OV64A40.patch @@ -0,0 +1,114 @@ +From 3d108604ca669b83bb4918c4f5f0a02ddef84972 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Sun, 1 Oct 2023 13:20:12 +0200 +Subject: [PATCH] media: dt-bindings: Add OmniVision OV64A40 + +Add bindings for OmniVision OV64A40. + +Signed-off-by: Jacopo Mondi +--- + .../bindings/media/i2c/ovti,ov64a40.yaml | 98 +++++++++++++++++++ + 1 file changed, 98 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/i2c/ovti,ov64a40.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov64a40.yaml +@@ -0,0 +1,98 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/i2c/ovti,ov64a40.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: OmniVision OV64A40 Image Sensor ++ ++maintainers: ++ - Jacopo Mondi ++ ++allOf: ++ - $ref: /schemas/media/video-interface-devices.yaml# ++ ++properties: ++ compatible: ++ const: ovti,ov64a40 ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ avdd-supply: ++ description: Analog voltage supply, 2.8 volts ++ ++ dvdd-supply: ++ description: Digital core voltage supply, 1.1 volts ++ ++ dovdd-supply: ++ description: Digital I/O voltage supply, 1.8 volts ++ ++ powerdown-gpios: ++ maxItems: 1 ++ ++ reset-gpios: ++ maxItems: 1 ++ ++ port: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ additionalProperties: false ++ ++ properties: ++ endpoint: ++ $ref: /schemas/media/video-interfaces.yaml# ++ additionalProperties: false ++ ++ properties: ++ bus-type: ++ enum: ++ - 1 # MIPI CSI-2 C-PHY ++ - 4 # MIPI CSI-2 D-PHY ++ data-lanes: true ++ link-frequencies: true ++ clock-noncontinuous: true ++ remote-endpoint: true ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - port ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ #include ++ ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ camera@36 { ++ compatible = "ovti,ov64a40"; ++ reg = <0x36>; ++ clocks = <&camera_clk>; ++ dovdd-supply = <&vgen4_reg>; ++ avdd-supply = <&vgen3_reg>; ++ dvdd-supply = <&vgen2_reg>; ++ powerdown-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; ++ rotation = <180>; ++ orientation = <2>; ++ ++ port { ++ endpoint { ++ remote-endpoint = <&mipi_csi2_in>; ++ bus-type = <4>; ++ data-lanes = <1 2 3 4>; ++ link-frequencies = /bits/ 64 <456000000>; ++ }; ++ }; ++ }; ++ }; ++ ++... diff --git a/target/linux/bcm27xx/patches-6.1/950-1194-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-1194-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch new file mode 100644 index 0000000000..82eda14173 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1194-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch @@ -0,0 +1,83 @@ +From 31c2999e543c245f7b96af3e73cd18e1036bfe7b Mon Sep 17 00:00:00 2001 +From: Kieran Bingham +Date: Thu, 14 Sep 2023 17:03:24 +0100 +Subject: [PATCH] media: dt-bindings: i2c: Add Rohm BU64754 bindings + +Add YAML device tree bindings for the ROHM BU64754 VCM Motor Driver for +Camera Autofocus. + +Signed-off-by: Kieran Bingham +Signed-off-by: Jacopo Mondi +--- + .../bindings/media/i2c/rohm,bu64754.yaml | 48 +++++++++++++++++++ + MAINTAINERS | 7 +++ + 2 files changed, 55 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/i2c/rohm,bu64754.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/i2c/rohm,bu64754.yaml +@@ -0,0 +1,48 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++# Copyright (C) 2023 Ideas on Board Oy. ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/i2c/rohm,bu64754.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: ROHM BU64754 Actuator Driver for Camera Autofocus ++ ++maintainers: ++ - Kieran Bingham ++ ++description: | ++ The BU64754GWZ is an actuator driver IC which can control the actuator ++ position precisely using an internal Hall Sensor. ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - rohm,bu64754 ++ ++ reg: ++ maxItems: 1 ++ ++ vdd-supply: ++ description: ++ Definition of the regulator used as VDD power supply to the driver. ++ ++required: ++ - compatible ++ - reg ++ ++additionalProperties: false ++ ++examples: ++ - | ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ lens@76 { ++ compatible = "rohm,bu64754"; ++ reg = <0x76>; ++ vdd-supply = <&cam1_reg>; ++ }; ++ }; ++... +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -17895,6 +17895,13 @@ S: Maintained + F: Documentation/devicetree/bindings/iio/light/bh1750.yaml + F: drivers/iio/light/bh1750.c + ++ROHM BU64754 MOTOR DRIVER FOR CAMERA AUTOFOCUS ++M: Kieran Bingham ++L: linux-media@vger.kernel.org ++S: Maintained ++T: git git://linuxtv.org/media_tree.git ++F: Documentation/devicetree/bindings/media/i2c/rohm,bu64754.yaml ++ + ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS + M: Marek Vasut + L: linux-kernel@vger.kernel.org diff --git a/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch b/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch new file mode 100644 index 0000000000..2f3ea4b072 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch @@ -0,0 +1,3763 @@ +From 87e3fcaad3017bdc91a7a79d2d1c874422ef87b0 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 20 Jul 2023 11:44:40 +0200 +Subject: [PATCH] media: i2c: Add driver for OmniVision OV64A40 + +Add a driver for the OmniVision OV64A40 image sensor. + +Signed-off-by: Jacopo Mondi +--- + MAINTAINERS | 8 + + drivers/media/i2c/Kconfig | 14 + + drivers/media/i2c/Makefile | 1 + + drivers/media/i2c/ov64a40.c | 3694 +++++++++++++++++++++++++++++++++++ + 4 files changed, 3717 insertions(+) + create mode 100644 drivers/media/i2c/ov64a40.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -15321,6 +15321,14 @@ S: Maintained + T: git git://linuxtv.org/media_tree.git + F: drivers/media/i2c/ov5695.c + ++OMNIVISION OV64A40 SENSOR DRIVER ++M: Jacopo Mondi ++L: linux-media@vger.kernel.org ++S: Maintained ++T: git git://linuxtv.org/media_tree.git ++F: Documentation/devicetree/bindings/media/i2c/ovti,ov64a40.yaml ++F: drivers/media/i2c/ov64a40.c ++ + OMNIVISION OV7670 SENSOR DRIVER + L: linux-media@vger.kernel.org + S: Orphan +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -631,6 +631,20 @@ config VIDEO_OV5695 + To compile this driver as a module, choose M here: the + module will be called ov5695. + ++config VIDEO_OV64A40 ++ tristate "OmniVision OV64A40 sensor support" ++ depends on I2C && VIDEO_DEV ++ select MEDIA_CONTROLLER ++ select VIDEO_V4L2_SUBDEV_API ++ select V4L2_FWNODE ++ select V4L2_CCI_I2C ++ help ++ This is a Video4Linux2 sensor driver for the OmniVision ++ OV64A40 camera. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ov64a40. ++ + config VIDEO_OV6650 + tristate "OmniVision OV6650 sensor support" + depends on I2C && VIDEO_DEV +--- a/drivers/media/i2c/Makefile ++++ b/drivers/media/i2c/Makefile +@@ -96,6 +96,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o + obj-$(CONFIG_VIDEO_OV5675) += ov5675.o + obj-$(CONFIG_VIDEO_OV5693) += ov5693.o + obj-$(CONFIG_VIDEO_OV5695) += ov5695.o ++obj-$(CONFIG_VIDEO_OV64A40) += ov64a40.o + obj-$(CONFIG_VIDEO_OV6650) += ov6650.o + obj-$(CONFIG_VIDEO_OV7251) += ov7251.o + obj-$(CONFIG_VIDEO_OV7640) += ov7640.o +--- /dev/null ++++ b/drivers/media/i2c/ov64a40.c +@@ -0,0 +1,3694 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * V4L2 sensor driver for OmniVision OV64A40 ++ * ++ * Copyright (C) 2023 Ideas On Board Oy ++ * Copyright (C) 2023 Arducam ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define OV64A40_XCLK_FREQ 24000000 ++ ++#define OV64A40_NATIVE_WIDTH 9286 ++#define OV64A40_NATIVE_HEIGHT 6976 ++#define OV64A40_PIXEL_ARRAY_TOP 0 ++#define OV64A40_PIXEL_ARRAY_LEFT 0 ++#define OV64A40_PIXEL_ARRAY_WIDTH 9248 ++#define OV64A40_PIXEL_ARRAY_HEIGHT 6944 ++ ++#define OV64A40_PIXEL_RATE 300000000 ++ ++#define OV64A40_LINK_FREQ_360M 360000000 ++#define OV64A40_LINK_FREQ_456M 456000000 ++ ++#define OV64A40_PLL1_PRE_DIV0 CCI_REG8(0x0301) ++#define OV64A40_PLL1_PRE_DIV CCI_REG8(0x0303) ++#define OV64A40_PLL1_MULTIPLIER CCI_REG16(0x0304) ++#define OV64A40_PLL1_M_DIV CCI_REG8(0x0307) ++#define OV64A40_PLL2_SEL_BAK_SA1 CCI_REG8(0x0320) ++#define OV64A40_PLL2_PRE_DIV CCI_REG8(0x0323) ++#define OV64A40_PLL2_MULTIPLIER CCI_REG16(0x0324) ++#define OV64A40_PLL2_PRE_DIV0 CCI_REG8(0x0326) ++#define OV64A40_PLL2_DIVDAC CCI_REG8(0x0329) ++#define OV64A40_PLL2_DIVSP CCI_REG8(0x032d) ++#define OV64A40_PLL2_DACPREDIV CCI_REG8(0x032e) ++ ++/* TODO: validate vblank_min, it's not characterized in the datasheet. */ ++#define OV64A40_VBLANK_MIN 128 ++#define OV64A40_VTS_MAX 0xffffff ++ ++#define OV64A40_REG_MEC_LONG_EXPO CCI_REG24(0x3500) ++#define OV64A40_EXPOSURE_MIN 16 ++#define OV64A40_EXPOSURE_MARGIN 32 ++ ++#define OV64A40_REG_MEC_LONG_GAIN CCI_REG16(0x3508) ++#define OV64A40_ANA_GAIN_MIN 0x80 ++#define OV64A40_ANA_GAIN_MAX 0x7ff ++#define OV64A40_ANA_GAIN_DEFAULT 0x80 ++ ++#define OV64A40_REG_TIMING_CTRL0 CCI_REG16(0x3800) ++#define OV64A40_REG_TIMING_CTRL2 CCI_REG16(0x3802) ++#define OV64A40_REG_TIMING_CTRL4 CCI_REG16(0x3804) ++#define OV64A40_REG_TIMING_CTRL6 CCI_REG16(0x3806) ++#define OV64A40_REG_TIMING_CTRL8 CCI_REG16(0x3808) ++#define OV64A40_REG_TIMING_CTRLA CCI_REG16(0x380a) ++#define OV64A40_REG_TIMING_CTRLC CCI_REG16(0x380c) ++#define OV64A40_REG_TIMING_CTRLE CCI_REG16(0x380e) ++#define OV64A40_REG_TIMING_CTRL10 CCI_REG16(0x3810) ++#define OV64A40_REG_TIMING_CTRL12 CCI_REG16(0x3812) ++ ++/* ++ * Careful: a typo in the datasheet calls this register ++ * OV64A40_REG_TIMING_CTRL20. ++ */ ++#define OV64A40_REG_TIMING_CTRL14 CCI_REG8(0x3814) ++#define OV64A40_REG_TIMING_CTRL15 CCI_REG8(0x3815) ++#define OV64A40_ODD_INC_SHIFT 4 ++#define OV64A40_SKIPPING_CONFIG(_odd, _even) \ ++ (((_odd) << OV64A40_ODD_INC_SHIFT) | (_even)) ++ ++#define OV64A40_REG_TIMING_CTRL_20 CCI_REG8(0x3820) ++#define OV64A40_TIMING_CTRL_20_VFLIP BIT(2) ++#define OV64A40_TIMING_CTRL_20_VBIN BIT(1) ++ ++#define OV64A40_REG_TIMING_CTRL_21 CCI_REG8(0x3821) ++#define OV64A40_TIMING_CTRL_21_HBIN BIT(4) ++#define OV64A40_TIMING_CTRL_21_HFLIP BIT(2) ++#define OV64A40_TIMING_CTRL_21_DSPEED BIT(0) ++#define OV64A40_TIMING_CTRL_21_HBIN_CONF \ ++ (OV64A40_TIMING_CTRL_21_HBIN | \ ++ OV64A40_TIMING_CTRL_21_DSPEED) ++ ++#define OV64A40_REG_TIMINGS_VTS_HIGH CCI_REG8(0x3840) ++#define OV64A40_REG_TIMINGS_VTS_MID CCI_REG8(0x380e) ++#define OV64A40_REG_TIMINGS_VTS_LOW CCI_REG8(0x380f) ++ ++/* The test pattern control is weirdly named PRE_ISP_2325_D2V2_TOP_1 in TRM. */ ++#define OV64A40_REG_TEST_PATTERN CCI_REG8(0x50c1) ++#define OV64A40_TEST_PATTERN_DISABLED 0x00 ++#define OV64A40_TEST_PATTERN_TYPE1 BIT(0) ++#define OV64A40_TEST_PATTERN_TYPE2 (BIT(4) | BIT(0)) ++#define OV64A40_TEST_PATTERN_TYPE3 (BIT(5) | BIT(0)) ++#define OV64A40_TEST_PATTERN_TYPE4 (BIT(5) | BIT(4) | BIT(0)) ++ ++#define OV64A40_REG_CHIP_ID CCI_REG24(0x300a) ++#define OV64A40_CHIP_ID 0x566441 ++ ++#define OV64A40_REG_SMIA CCI_REG8(0x0100) ++#define OV64A40_REG_SMIA_STREAMING BIT(0) ++ ++enum ov64a40_link_freq_ids { ++ OV64A40_LINK_FREQ_456M_ID, ++ OV64A40_LINK_FREQ_360M_ID, ++ OV64A40_NUM_LINK_FREQ, ++}; ++ ++static const char * const ov64a40_supply_names[] = { ++ /* Supplies can be enabled in any order */ ++ "avdd", /* Analog (2.8V) supply */ ++ "dovdd", /* Digital Core (1.8V) supply */ ++ "dvdd", /* IF (1.1V) supply */ ++}; ++ ++static const char * const ov64a40_test_pattern_menu[] = { ++ "Disabled", ++ "Type1", ++ "Type2", ++ "Type3", ++ "Type4", ++}; ++ ++static const int ov64a40_test_pattern_val[] = { ++ OV64A40_TEST_PATTERN_DISABLED, ++ OV64A40_TEST_PATTERN_TYPE1, ++ OV64A40_TEST_PATTERN_TYPE2, ++ OV64A40_TEST_PATTERN_TYPE3, ++ OV64A40_TEST_PATTERN_TYPE4, ++}; ++ ++static const unsigned int ov64a40_mbus_codes[] = { ++ MEDIA_BUS_FMT_SBGGR10_1X10, ++ MEDIA_BUS_FMT_SGRBG10_1X10, ++ MEDIA_BUS_FMT_SGBRG10_1X10, ++ MEDIA_BUS_FMT_SRGGB10_1X10, ++}; ++ ++static const struct cci_reg_sequence ov64a40_init[] = { ++ { CCI_REG8(0x0103), 0x01 }, { CCI_REG8(0x0301), 0x88 }, ++ { CCI_REG8(0x0304), 0x00 }, { CCI_REG8(0x0305), 0x96 }, ++ { CCI_REG8(0x0306), 0x03 }, { CCI_REG8(0x0307), 0x00 }, ++ { CCI_REG8(0x0345), 0x2c }, { CCI_REG8(0x034a), 0x02 }, ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x0350), 0xc0 }, ++ { CCI_REG8(0x0360), 0x09 }, { CCI_REG8(0x3012), 0x31 }, ++ { CCI_REG8(0x3015), 0xf0 }, { CCI_REG8(0x3017), 0xf0 }, ++ { CCI_REG8(0x301d), 0xf6 }, { CCI_REG8(0x301e), 0xf1 }, ++ { CCI_REG8(0x3022), 0xf0 }, { CCI_REG8(0x3400), 0x08 }, ++ { CCI_REG8(0x3608), 0x41 }, { CCI_REG8(0x3421), 0x02 }, ++ { CCI_REG8(0x3500), 0x00 }, { CCI_REG8(0x3501), 0x00 }, ++ { CCI_REG8(0x3502), 0x18 }, { CCI_REG8(0x3504), 0x0c }, ++ { CCI_REG8(0x3508), 0x01 }, { CCI_REG8(0x3509), 0x00 }, ++ { CCI_REG8(0x350a), 0x01 }, { CCI_REG8(0x350b), 0x00 }, ++ { CCI_REG8(0x350b), 0x00 }, { CCI_REG8(0x3540), 0x00 }, ++ { CCI_REG8(0x3541), 0x00 }, { CCI_REG8(0x3542), 0x08 }, ++ { CCI_REG8(0x3548), 0x01 }, { CCI_REG8(0x3549), 0xa0 }, ++ { CCI_REG8(0x3549), 0x00 }, { CCI_REG8(0x3549), 0x00 }, ++ { CCI_REG8(0x3549), 0x00 }, { CCI_REG8(0x3580), 0x00 }, ++ { CCI_REG8(0x3581), 0x00 }, { CCI_REG8(0x3582), 0x04 }, ++ { CCI_REG8(0x3588), 0x01 }, { CCI_REG8(0x3589), 0xf0 }, ++ { CCI_REG8(0x3589), 0x00 }, { CCI_REG8(0x3589), 0x00 }, ++ { CCI_REG8(0x3589), 0x00 }, { CCI_REG8(0x360d), 0x83 }, ++ { CCI_REG8(0x3616), 0xa0 }, { CCI_REG8(0x3617), 0x31 }, ++ { CCI_REG8(0x3623), 0x10 }, { CCI_REG8(0x3633), 0x03 }, ++ { CCI_REG8(0x3634), 0x03 }, { CCI_REG8(0x3635), 0x77 }, ++ { CCI_REG8(0x3640), 0x19 }, { CCI_REG8(0x3641), 0x80 }, ++ { CCI_REG8(0x364d), 0x0f }, { CCI_REG8(0x3680), 0x80 }, ++ { CCI_REG8(0x3682), 0x00 }, { CCI_REG8(0x3683), 0x00 }, ++ { CCI_REG8(0x3684), 0x07 }, { CCI_REG8(0x3688), 0x01 }, ++ { CCI_REG8(0x3689), 0x08 }, { CCI_REG8(0x368a), 0x26 }, ++ { CCI_REG8(0x368b), 0xc8 }, { CCI_REG8(0x368e), 0x70 }, ++ { CCI_REG8(0x368f), 0x00 }, { CCI_REG8(0x3692), 0x04 }, ++ { CCI_REG8(0x3693), 0x00 }, { CCI_REG8(0x3696), 0xd1 }, ++ { CCI_REG8(0x3697), 0xe0 }, { CCI_REG8(0x3698), 0x80 }, ++ { CCI_REG8(0x3699), 0x2b }, { CCI_REG8(0x369a), 0x00 }, ++ { CCI_REG8(0x369d), 0x00 }, { CCI_REG8(0x369e), 0x14 }, ++ { CCI_REG8(0x369f), 0x20 }, { CCI_REG8(0x36a5), 0x80 }, ++ { CCI_REG8(0x36a6), 0x00 }, { CCI_REG8(0x36a7), 0x00 }, ++ { CCI_REG8(0x36a8), 0x00 }, { CCI_REG8(0x36b5), 0x17 }, ++ { CCI_REG8(0x3701), 0x30 }, { CCI_REG8(0x3706), 0x2b }, ++ { CCI_REG8(0x3709), 0x8d }, { CCI_REG8(0x370b), 0x4f }, ++ { CCI_REG8(0x3711), 0x00 }, { CCI_REG8(0x3712), 0x01 }, ++ { CCI_REG8(0x3713), 0x00 }, { CCI_REG8(0x3720), 0x08 }, ++ { CCI_REG8(0x3727), 0x22 }, { CCI_REG8(0x3728), 0x01 }, ++ { CCI_REG8(0x375e), 0x00 }, { CCI_REG8(0x3760), 0x08 }, ++ { CCI_REG8(0x3761), 0x10 }, { CCI_REG8(0x3762), 0x08 }, ++ { CCI_REG8(0x3765), 0x10 }, { CCI_REG8(0x3766), 0x18 }, ++ { CCI_REG8(0x376a), 0x08 }, { CCI_REG8(0x376b), 0x00 }, ++ { CCI_REG8(0x376d), 0x1b }, { CCI_REG8(0x3791), 0x2b }, ++ { CCI_REG8(0x3793), 0x2b }, { CCI_REG8(0x3795), 0x2b }, ++ { CCI_REG8(0x3797), 0x4f }, { CCI_REG8(0x3799), 0x4f }, ++ { CCI_REG8(0x379b), 0x4f }, { CCI_REG8(0x37a0), 0x22 }, ++ { CCI_REG8(0x37da), 0x04 }, { CCI_REG8(0x37f9), 0x02 }, ++ { CCI_REG8(0x37fa), 0x02 }, { CCI_REG8(0x37fb), 0x02 }, ++ { CCI_REG8(0x3814), 0x11 }, { CCI_REG8(0x3815), 0x11 }, ++ { CCI_REG8(0x3820), 0x40 }, { CCI_REG8(0x3821), 0x04 }, ++ { CCI_REG8(0x3822), 0x00 }, { CCI_REG8(0x3823), 0x04 }, ++ { CCI_REG8(0x3827), 0x08 }, { CCI_REG8(0x3828), 0x00 }, ++ { CCI_REG8(0x382a), 0x81 }, { CCI_REG8(0x382e), 0x70 }, ++ { CCI_REG8(0x3837), 0x10 }, { CCI_REG8(0x3839), 0x00 }, ++ { CCI_REG8(0x383b), 0x00 }, { CCI_REG8(0x383c), 0x00 }, ++ { CCI_REG8(0x383d), 0x10 }, { CCI_REG8(0x383f), 0x00 }, ++ { CCI_REG8(0x384c), 0x02 }, { CCI_REG8(0x384d), 0x8c }, ++ { CCI_REG8(0x3852), 0x00 }, { CCI_REG8(0x3856), 0x10 }, ++ { CCI_REG8(0x3857), 0x10 }, { CCI_REG8(0x3858), 0x20 }, ++ { CCI_REG8(0x3859), 0x20 }, { CCI_REG8(0x3894), 0x00 }, ++ { CCI_REG8(0x3895), 0x00 }, { CCI_REG8(0x3896), 0x00 }, ++ { CCI_REG8(0x3897), 0x00 }, { CCI_REG8(0x3900), 0x40 }, ++ { CCI_REG8(0x3aed), 0x6e }, { CCI_REG8(0x3af1), 0x73 }, ++ { CCI_REG8(0x3d86), 0x12 }, { CCI_REG8(0x3d87), 0x30 }, ++ { CCI_REG8(0x3d8c), 0xab }, { CCI_REG8(0x3d8d), 0xb0 }, ++ { CCI_REG8(0x3f00), 0x12 }, { CCI_REG8(0x3f00), 0x12 }, ++ { CCI_REG8(0x3f00), 0x12 }, { CCI_REG8(0x3f01), 0x03 }, ++ { CCI_REG8(0x4009), 0x01 }, { CCI_REG8(0x400e), 0xc6 }, ++ { CCI_REG8(0x400f), 0x00 }, { CCI_REG8(0x4010), 0x28 }, ++ { CCI_REG8(0x4011), 0x01 }, { CCI_REG8(0x4012), 0x0c }, ++ { CCI_REG8(0x4015), 0x00 }, { CCI_REG8(0x4016), 0x1f }, ++ { CCI_REG8(0x4017), 0x00 }, { CCI_REG8(0x4018), 0x07 }, ++ { CCI_REG8(0x401a), 0x40 }, { CCI_REG8(0x4028), 0x01 }, ++ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4506), 0x01 }, ++ { CCI_REG8(0x4508), 0x00 }, { CCI_REG8(0x4509), 0x35 }, ++ { CCI_REG8(0x450a), 0x08 }, { CCI_REG8(0x450c), 0x00 }, ++ { CCI_REG8(0x450d), 0x20 }, { CCI_REG8(0x450e), 0x00 }, ++ { CCI_REG8(0x450f), 0x20 }, { CCI_REG8(0x451e), 0x00 }, ++ { CCI_REG8(0x451f), 0x00 }, { CCI_REG8(0x4523), 0x00 }, ++ { CCI_REG8(0x4526), 0x00 }, { CCI_REG8(0x4527), 0x18 }, ++ { CCI_REG8(0x4580), 0x01 }, { CCI_REG8(0x4583), 0x00 }, ++ { CCI_REG8(0x4584), 0x00 }, { CCI_REG8(0x45c0), 0xa1 }, ++ { CCI_REG8(0x4602), 0x08 }, { CCI_REG8(0x4603), 0x05 }, ++ { CCI_REG8(0x4606), 0x12 }, { CCI_REG8(0x4607), 0x30 }, ++ { CCI_REG8(0x460b), 0x00 }, { CCI_REG8(0x460d), 0x00 }, ++ { CCI_REG8(0x4640), 0x00 }, { CCI_REG8(0x4641), 0x24 }, ++ { CCI_REG8(0x4643), 0x08 }, { CCI_REG8(0x4645), 0x14 }, ++ { CCI_REG8(0x4648), 0x0a }, { CCI_REG8(0x4649), 0x06 }, ++ { CCI_REG8(0x464a), 0x00 }, { CCI_REG8(0x464b), 0x30 }, ++ { CCI_REG8(0x4800), 0x04 }, { CCI_REG8(0x4802), 0x02 }, ++ { CCI_REG8(0x480b), 0x10 }, { CCI_REG8(0x480c), 0x80 }, ++ { CCI_REG8(0x480e), 0x04 }, { CCI_REG8(0x480f), 0x32 }, ++ { CCI_REG8(0x481b), 0x12 }, { CCI_REG8(0x4833), 0x30 }, ++ { CCI_REG8(0x4837), 0x08 }, { CCI_REG8(0x484b), 0x27 }, ++ { CCI_REG8(0x4850), 0x42 }, { CCI_REG8(0x4851), 0xaa }, ++ { CCI_REG8(0x4860), 0x01 }, { CCI_REG8(0x4861), 0xec }, ++ { CCI_REG8(0x4862), 0x25 }, { CCI_REG8(0x4888), 0x00 }, ++ { CCI_REG8(0x4889), 0x03 }, { CCI_REG8(0x488c), 0x60 }, ++ { CCI_REG8(0x4910), 0x28 }, { CCI_REG8(0x4911), 0x01 }, ++ { CCI_REG8(0x4912), 0x0c }, { CCI_REG8(0x491a), 0x40 }, ++ { CCI_REG8(0x4915), 0x00 }, { CCI_REG8(0x4916), 0x0f }, ++ { CCI_REG8(0x4917), 0x00 }, { CCI_REG8(0x4918), 0x07 }, ++ { CCI_REG8(0x4a10), 0x28 }, { CCI_REG8(0x4a11), 0x01 }, ++ { CCI_REG8(0x4a12), 0x0c }, { CCI_REG8(0x4a1a), 0x40 }, ++ { CCI_REG8(0x4a15), 0x00 }, { CCI_REG8(0x4a16), 0x0f }, ++ { CCI_REG8(0x4a17), 0x00 }, { CCI_REG8(0x4a18), 0x07 }, ++ { CCI_REG8(0x4d00), 0x04 }, { CCI_REG8(0x4d01), 0x5a }, ++ { CCI_REG8(0x4d02), 0xbb }, { CCI_REG8(0x4d03), 0x84 }, ++ { CCI_REG8(0x4d04), 0xd1 }, { CCI_REG8(0x4d05), 0x68 }, ++ { CCI_REG8(0xc4fa), 0x10 }, { CCI_REG8(0x3b56), 0x0a }, ++ { CCI_REG8(0x3b57), 0x0a }, { CCI_REG8(0x3b58), 0x0c }, ++ { CCI_REG8(0x3b59), 0x10 }, { CCI_REG8(0x3a1d), 0x30 }, ++ { CCI_REG8(0x3a1e), 0x30 }, { CCI_REG8(0x3a21), 0x30 }, ++ { CCI_REG8(0x3a22), 0x30 }, { CCI_REG8(0x3992), 0x02 }, ++ { CCI_REG8(0x399e), 0x02 }, { CCI_REG8(0x39fb), 0x30 }, ++ { CCI_REG8(0x39fc), 0x30 }, { CCI_REG8(0x39fd), 0x30 }, ++ { CCI_REG8(0x39fe), 0x30 }, { CCI_REG8(0x3a6d), 0x83 }, ++ { CCI_REG8(0x3a5e), 0x83 }, { CCI_REG8(0xc500), 0x12 }, ++ { CCI_REG8(0xc501), 0x12 }, { CCI_REG8(0xc502), 0x12 }, ++ { CCI_REG8(0xc503), 0x12 }, { CCI_REG8(0xc505), 0x12 }, ++ { CCI_REG8(0xc506), 0x12 }, { CCI_REG8(0xc507), 0x12 }, ++ { CCI_REG8(0xc508), 0x12 }, { CCI_REG8(0x3a77), 0x12 }, ++ { CCI_REG8(0x3a73), 0x12 }, { CCI_REG8(0x3a7b), 0x12 }, ++ { CCI_REG8(0x3a7f), 0x12 }, { CCI_REG8(0x3b2e), 0x13 }, ++ { CCI_REG8(0x3b29), 0x13 }, { CCI_REG8(0xc439), 0x13 }, ++ { CCI_REG8(0xc469), 0x13 }, { CCI_REG8(0xc41c), 0x89 }, ++ { CCI_REG8(0x3618), 0x80 }, { CCI_REG8(0xc514), 0x51 }, ++ { CCI_REG8(0xc515), 0x2c }, { CCI_REG8(0xc516), 0x16 }, ++ { CCI_REG8(0xc517), 0x0d }, { CCI_REG8(0x3615), 0x7f }, ++ { CCI_REG8(0x3632), 0x99 }, { CCI_REG8(0x3642), 0x00 }, ++ { CCI_REG8(0x3645), 0x80 }, { CCI_REG8(0x3702), 0x2a }, ++ { CCI_REG8(0x3703), 0x2a }, { CCI_REG8(0x3708), 0x2f }, ++ { CCI_REG8(0x3721), 0x15 }, { CCI_REG8(0x3744), 0x28 }, ++ { CCI_REG8(0x3991), 0x0c }, { CCI_REG8(0x371d), 0x24 }, ++ { CCI_REG8(0x371f), 0x0c }, { CCI_REG8(0x374b), 0x03 }, ++ { CCI_REG8(0x37d0), 0x00 }, { CCI_REG8(0x391d), 0x55 }, ++ { CCI_REG8(0x391e), 0x52 }, { CCI_REG8(0x399d), 0x0c }, ++ { CCI_REG8(0x3a2f), 0x01 }, { CCI_REG8(0x3a30), 0x01 }, ++ { CCI_REG8(0x3a31), 0x01 }, { CCI_REG8(0x3a32), 0x01 }, ++ { CCI_REG8(0x3a34), 0x01 }, { CCI_REG8(0x3a35), 0x01 }, ++ { CCI_REG8(0x3a36), 0x01 }, { CCI_REG8(0x3a37), 0x01 }, ++ { CCI_REG8(0x3a43), 0x01 }, { CCI_REG8(0x3a44), 0x01 }, ++ { CCI_REG8(0x3a45), 0x01 }, { CCI_REG8(0x3a46), 0x01 }, ++ { CCI_REG8(0x3a48), 0x01 }, { CCI_REG8(0x3a49), 0x01 }, ++ { CCI_REG8(0x3a4a), 0x01 }, { CCI_REG8(0x3a4b), 0x01 }, ++ { CCI_REG8(0x3a50), 0x14 }, { CCI_REG8(0x3a54), 0x14 }, ++ { CCI_REG8(0x3a60), 0x20 }, { CCI_REG8(0x3a6f), 0x20 }, ++ { CCI_REG8(0x3ac5), 0x01 }, { CCI_REG8(0x3ac6), 0x01 }, ++ { CCI_REG8(0x3ac7), 0x01 }, { CCI_REG8(0x3ac8), 0x01 }, ++ { CCI_REG8(0x3ac9), 0x01 }, { CCI_REG8(0x3aca), 0x01 }, ++ { CCI_REG8(0x3acb), 0x01 }, { CCI_REG8(0x3acc), 0x01 }, ++ { CCI_REG8(0x3acd), 0x01 }, { CCI_REG8(0x3ace), 0x01 }, ++ { CCI_REG8(0x3acf), 0x01 }, { CCI_REG8(0x3ad0), 0x01 }, ++ { CCI_REG8(0x3ad1), 0x01 }, { CCI_REG8(0x3ad2), 0x01 }, ++ { CCI_REG8(0x3ad3), 0x01 }, { CCI_REG8(0x3ad4), 0x01 }, ++ { CCI_REG8(0x3add), 0x1f }, { CCI_REG8(0x3adf), 0x24 }, ++ { CCI_REG8(0x3aef), 0x1f }, { CCI_REG8(0x3af0), 0x24 }, ++ { CCI_REG8(0x3b92), 0x08 }, { CCI_REG8(0x3b93), 0x08 }, ++ { CCI_REG8(0x3b94), 0x08 }, { CCI_REG8(0x3b95), 0x08 }, ++ { CCI_REG8(0x3be7), 0x1e }, { CCI_REG8(0x3be8), 0x26 }, ++ { CCI_REG8(0xc44a), 0x20 }, { CCI_REG8(0xc44c), 0x20 }, ++ { CCI_REG8(0xc483), 0x00 }, { CCI_REG8(0xc484), 0x00 }, ++ { CCI_REG8(0xc485), 0x00 }, { CCI_REG8(0xc486), 0x00 }, ++ { CCI_REG8(0xc487), 0x01 }, { CCI_REG8(0xc488), 0x01 }, ++ { CCI_REG8(0xc489), 0x01 }, { CCI_REG8(0xc48a), 0x01 }, ++ { CCI_REG8(0xc4c1), 0x00 }, { CCI_REG8(0xc4c2), 0x00 }, ++ { CCI_REG8(0xc4c3), 0x00 }, { CCI_REG8(0xc4c4), 0x00 }, ++ { CCI_REG8(0xc4c6), 0x10 }, { CCI_REG8(0xc4c7), 0x10 }, ++ { CCI_REG8(0xc4c8), 0x10 }, { CCI_REG8(0xc4c9), 0x10 }, ++ { CCI_REG8(0xc4ca), 0x10 }, { CCI_REG8(0xc4cb), 0x10 }, ++ { CCI_REG8(0xc4cc), 0x10 }, { CCI_REG8(0xc4cd), 0x10 }, ++ { CCI_REG8(0xc4ea), 0x07 }, { CCI_REG8(0xc4eb), 0x07 }, ++ { CCI_REG8(0xc4ec), 0x07 }, { CCI_REG8(0xc4ed), 0x07 }, ++ { CCI_REG8(0xc4ee), 0x07 }, { CCI_REG8(0xc4f6), 0x10 }, ++ { CCI_REG8(0xc4f7), 0x10 }, { CCI_REG8(0xc4f8), 0x10 }, ++ { CCI_REG8(0xc4f9), 0x10 }, { CCI_REG8(0xc518), 0x0e }, ++ { CCI_REG8(0xc519), 0x0e }, { CCI_REG8(0xc51a), 0x0e }, ++ { CCI_REG8(0xc51b), 0x0e }, { CCI_REG8(0xc51c), 0x0e }, ++ { CCI_REG8(0xc51d), 0x0e }, { CCI_REG8(0xc51e), 0x0e }, ++ { CCI_REG8(0xc51f), 0x0e }, { CCI_REG8(0xc520), 0x0e }, ++ { CCI_REG8(0xc521), 0x0e }, { CCI_REG8(0xc522), 0x0e }, ++ { CCI_REG8(0xc523), 0x0e }, { CCI_REG8(0xc524), 0x0e }, ++ { CCI_REG8(0xc525), 0x0e }, { CCI_REG8(0xc526), 0x0e }, ++ { CCI_REG8(0xc527), 0x0e }, { CCI_REG8(0xc528), 0x0e }, ++ { CCI_REG8(0xc529), 0x0e }, { CCI_REG8(0xc52a), 0x0e }, ++ { CCI_REG8(0xc52b), 0x0e }, { CCI_REG8(0xc52c), 0x0e }, ++ { CCI_REG8(0xc52d), 0x0e }, { CCI_REG8(0xc52e), 0x0e }, ++ { CCI_REG8(0xc52f), 0x0e }, { CCI_REG8(0xc530), 0x0e }, ++ { CCI_REG8(0xc531), 0x0e }, { CCI_REG8(0xc532), 0x0e }, ++ { CCI_REG8(0xc533), 0x0e }, { CCI_REG8(0xc534), 0x0e }, ++ { CCI_REG8(0xc535), 0x0e }, { CCI_REG8(0xc536), 0x0e }, ++ { CCI_REG8(0xc537), 0x0e }, { CCI_REG8(0xc538), 0x0e }, ++ { CCI_REG8(0xc539), 0x0e }, { CCI_REG8(0xc53a), 0x0e }, ++ { CCI_REG8(0xc53b), 0x0e }, { CCI_REG8(0xc53c), 0x0e }, ++ { CCI_REG8(0xc53d), 0x0e }, { CCI_REG8(0xc53e), 0x0e }, ++ { CCI_REG8(0xc53f), 0x0e }, { CCI_REG8(0xc540), 0x0e }, ++ { CCI_REG8(0xc541), 0x0e }, { CCI_REG8(0xc542), 0x0e }, ++ { CCI_REG8(0xc543), 0x0e }, { CCI_REG8(0xc544), 0x0e }, ++ { CCI_REG8(0xc545), 0x0e }, { CCI_REG8(0xc546), 0x0e }, ++ { CCI_REG8(0xc547), 0x0e }, { CCI_REG8(0xc548), 0x0e }, ++ { CCI_REG8(0xc549), 0x0e }, { CCI_REG8(0xc57f), 0x22 }, ++ { CCI_REG8(0xc580), 0x22 }, { CCI_REG8(0xc581), 0x22 }, ++ { CCI_REG8(0xc582), 0x22 }, { CCI_REG8(0xc583), 0x22 }, ++ { CCI_REG8(0xc584), 0x22 }, { CCI_REG8(0xc585), 0x22 }, ++ { CCI_REG8(0xc586), 0x22 }, { CCI_REG8(0xc587), 0x22 }, ++ { CCI_REG8(0xc588), 0x22 }, { CCI_REG8(0xc589), 0x22 }, ++ { CCI_REG8(0xc58a), 0x22 }, { CCI_REG8(0xc58b), 0x22 }, ++ { CCI_REG8(0xc58c), 0x22 }, { CCI_REG8(0xc58d), 0x22 }, ++ { CCI_REG8(0xc58e), 0x22 }, { CCI_REG8(0xc58f), 0x22 }, ++ { CCI_REG8(0xc590), 0x22 }, { CCI_REG8(0xc591), 0x22 }, ++ { CCI_REG8(0xc592), 0x22 }, { CCI_REG8(0xc598), 0x22 }, ++ { CCI_REG8(0xc599), 0x22 }, { CCI_REG8(0xc59a), 0x22 }, ++ { CCI_REG8(0xc59b), 0x22 }, { CCI_REG8(0xc59c), 0x22 }, ++ { CCI_REG8(0xc59d), 0x22 }, { CCI_REG8(0xc59e), 0x22 }, ++ { CCI_REG8(0xc59f), 0x22 }, { CCI_REG8(0xc5a0), 0x22 }, ++ { CCI_REG8(0xc5a1), 0x22 }, { CCI_REG8(0xc5a2), 0x22 }, ++ { CCI_REG8(0xc5a3), 0x22 }, { CCI_REG8(0xc5a4), 0x22 }, ++ { CCI_REG8(0xc5a5), 0x22 }, { CCI_REG8(0xc5a6), 0x22 }, ++ { CCI_REG8(0xc5a7), 0x22 }, { CCI_REG8(0xc5a8), 0x22 }, ++ { CCI_REG8(0xc5a9), 0x22 }, { CCI_REG8(0xc5aa), 0x22 }, ++ { CCI_REG8(0xc5ab), 0x22 }, { CCI_REG8(0xc5b1), 0x2a }, ++ { CCI_REG8(0xc5b2), 0x2a }, { CCI_REG8(0xc5b3), 0x2a }, ++ { CCI_REG8(0xc5b4), 0x2a }, { CCI_REG8(0xc5b5), 0x2a }, ++ { CCI_REG8(0xc5b6), 0x2a }, { CCI_REG8(0xc5b7), 0x2a }, ++ { CCI_REG8(0xc5b8), 0x2a }, { CCI_REG8(0xc5b9), 0x2a }, ++ { CCI_REG8(0xc5ba), 0x2a }, { CCI_REG8(0xc5bb), 0x2a }, ++ { CCI_REG8(0xc5bc), 0x2a }, { CCI_REG8(0xc5bd), 0x2a }, ++ { CCI_REG8(0xc5be), 0x2a }, { CCI_REG8(0xc5bf), 0x2a }, ++ { CCI_REG8(0xc5c0), 0x2a }, { CCI_REG8(0xc5c1), 0x2a }, ++ { CCI_REG8(0xc5c2), 0x2a }, { CCI_REG8(0xc5c3), 0x2a }, ++ { CCI_REG8(0xc5c4), 0x2a }, { CCI_REG8(0xc5ca), 0x2a }, ++ { CCI_REG8(0xc5cb), 0x2a }, { CCI_REG8(0xc5cc), 0x2a }, ++ { CCI_REG8(0xc5cd), 0x2a }, { CCI_REG8(0xc5ce), 0x2a }, ++ { CCI_REG8(0xc5cf), 0x2a }, { CCI_REG8(0xc5d0), 0x2a }, ++ { CCI_REG8(0xc5d1), 0x2a }, { CCI_REG8(0xc5d2), 0x2a }, ++ { CCI_REG8(0xc5d3), 0x2a }, { CCI_REG8(0xc5d4), 0x2a }, ++ { CCI_REG8(0xc5d5), 0x2a }, { CCI_REG8(0xc5d6), 0x2a }, ++ { CCI_REG8(0xc5d7), 0x2a }, { CCI_REG8(0xc5d8), 0x2a }, ++ { CCI_REG8(0xc5d9), 0x2a }, { CCI_REG8(0xc5da), 0x2a }, ++ { CCI_REG8(0xc5db), 0x2a }, { CCI_REG8(0xc5dc), 0x2a }, ++ { CCI_REG8(0xc5dd), 0x2a }, { CCI_REG8(0xc5e8), 0x22 }, ++ { CCI_REG8(0xc5ea), 0x22 }, { CCI_REG8(0x4540), 0x12 }, ++ { CCI_REG8(0x4541), 0x30 }, { CCI_REG8(0x3d86), 0x12 }, ++ { CCI_REG8(0x3d87), 0x30 }, { CCI_REG8(0x4606), 0x12 }, ++ { CCI_REG8(0x4607), 0x30 }, { CCI_REG8(0x4648), 0x0a }, ++ { CCI_REG8(0x4649), 0x06 }, { CCI_REG8(0x3220), 0x12 }, ++ { CCI_REG8(0x3221), 0x30 }, { CCI_REG8(0x40c2), 0x12 }, ++ { CCI_REG8(0x49c2), 0x12 }, { CCI_REG8(0x4ac2), 0x12 }, ++ { CCI_REG8(0x40c3), 0x30 }, { CCI_REG8(0x49c3), 0x30 }, ++ { CCI_REG8(0x4ac3), 0x30 }, { CCI_REG8(0x36b0), 0x12 }, ++ { CCI_REG8(0x36b1), 0x30 }, { CCI_REG8(0x45cb), 0x12 }, ++ { CCI_REG8(0x45cc), 0x30 }, { CCI_REG8(0x4585), 0x12 }, ++ { CCI_REG8(0x4586), 0x30 }, { CCI_REG8(0x36b2), 0x12 }, ++ { CCI_REG8(0x36b3), 0x30 }, { CCI_REG8(0x5a40), 0x75 }, ++ { CCI_REG8(0x5a41), 0x75 }, { CCI_REG8(0x5a42), 0x75 }, ++ { CCI_REG8(0x5a43), 0x75 }, { CCI_REG8(0x5a44), 0x75 }, ++ { CCI_REG8(0x5a45), 0x75 }, { CCI_REG8(0x5a46), 0x75 }, ++ { CCI_REG8(0x5a47), 0x75 }, { CCI_REG8(0x5a48), 0x75 }, ++ { CCI_REG8(0x5a49), 0x75 }, { CCI_REG8(0x5a4a), 0x75 }, ++ { CCI_REG8(0x5a4b), 0x75 }, { CCI_REG8(0x5a4c), 0x75 }, ++ { CCI_REG8(0x5a4d), 0x75 }, { CCI_REG8(0x5a4e), 0x75 }, ++ { CCI_REG8(0x5a4f), 0x75 }, { CCI_REG8(0x5a50), 0x75 }, ++ { CCI_REG8(0x5a51), 0x75 }, { CCI_REG8(0x5a52), 0x75 }, ++ { CCI_REG8(0x5a53), 0x75 }, { CCI_REG8(0x5a54), 0x75 }, ++ { CCI_REG8(0x5a55), 0x75 }, { CCI_REG8(0x5a56), 0x75 }, ++ { CCI_REG8(0x5a57), 0x75 }, { CCI_REG8(0x5a58), 0x75 }, ++ { CCI_REG8(0x5a59), 0x75 }, { CCI_REG8(0x5a5a), 0x75 }, ++ { CCI_REG8(0x5a5b), 0x75 }, { CCI_REG8(0x5a5c), 0x75 }, ++ { CCI_REG8(0x5a5d), 0x75 }, { CCI_REG8(0x5a5e), 0x75 }, ++ { CCI_REG8(0x5a5f), 0x75 }, { CCI_REG8(0x5a60), 0x75 }, ++ { CCI_REG8(0x5a61), 0x75 }, { CCI_REG8(0x5a62), 0x75 }, ++ { CCI_REG8(0x5a63), 0x75 }, { CCI_REG8(0x5a64), 0x75 }, ++ { CCI_REG8(0x5a65), 0x75 }, { CCI_REG8(0x5a66), 0x75 }, ++ { CCI_REG8(0x5a67), 0x75 }, { CCI_REG8(0x5a68), 0x75 }, ++ { CCI_REG8(0x5a69), 0x75 }, { CCI_REG8(0x5a6a), 0x75 }, ++ { CCI_REG8(0x5a6b), 0x75 }, { CCI_REG8(0x5a6c), 0x75 }, ++ { CCI_REG8(0x5a6d), 0x75 }, { CCI_REG8(0x5a6e), 0x75 }, ++ { CCI_REG8(0x5a6f), 0x75 }, { CCI_REG8(0x5a70), 0x75 }, ++ { CCI_REG8(0x5a71), 0x75 }, { CCI_REG8(0x5a72), 0x75 }, ++ { CCI_REG8(0x5a73), 0x75 }, { CCI_REG8(0x5a74), 0x75 }, ++ { CCI_REG8(0x5a75), 0x75 }, { CCI_REG8(0x5a76), 0x75 }, ++ { CCI_REG8(0x5a77), 0x75 }, { CCI_REG8(0x5a78), 0x75 }, ++ { CCI_REG8(0x5a79), 0x75 }, { CCI_REG8(0x5a7a), 0x75 }, ++ { CCI_REG8(0x5a7b), 0x75 }, { CCI_REG8(0x5a7c), 0x75 }, ++ { CCI_REG8(0x5a7d), 0x75 }, { CCI_REG8(0x5a7e), 0x75 }, ++ { CCI_REG8(0x5a7f), 0x75 }, { CCI_REG8(0x5a80), 0x75 }, ++ { CCI_REG8(0x5a81), 0x75 }, { CCI_REG8(0x5a82), 0x75 }, ++ { CCI_REG8(0x5a83), 0x75 }, { CCI_REG8(0x5a84), 0x75 }, ++ { CCI_REG8(0x5a85), 0x75 }, { CCI_REG8(0x5a86), 0x75 }, ++ { CCI_REG8(0x5a87), 0x75 }, { CCI_REG8(0x5a88), 0x75 }, ++ { CCI_REG8(0x5a89), 0x75 }, { CCI_REG8(0x5a8a), 0x75 }, ++ { CCI_REG8(0x5a8b), 0x75 }, { CCI_REG8(0x5a8c), 0x75 }, ++ { CCI_REG8(0x5a8d), 0x75 }, { CCI_REG8(0x5a8e), 0x75 }, ++ { CCI_REG8(0x5a8f), 0x75 }, { CCI_REG8(0x5a90), 0x75 }, ++ { CCI_REG8(0x5a91), 0x75 }, { CCI_REG8(0x5a92), 0x75 }, ++ { CCI_REG8(0x5a93), 0x75 }, { CCI_REG8(0x5a94), 0x75 }, ++ { CCI_REG8(0x5a95), 0x75 }, { CCI_REG8(0x5a96), 0x75 }, ++ { CCI_REG8(0x5a97), 0x75 }, { CCI_REG8(0x5a98), 0x75 }, ++ { CCI_REG8(0x5a99), 0x75 }, { CCI_REG8(0x5a9a), 0x75 }, ++ { CCI_REG8(0x5a9b), 0x75 }, { CCI_REG8(0x5a9c), 0x75 }, ++ { CCI_REG8(0x5a9d), 0x75 }, { CCI_REG8(0x5a9e), 0x75 }, ++ { CCI_REG8(0x5a9f), 0x75 }, { CCI_REG8(0x5aa0), 0x75 }, ++ { CCI_REG8(0x5aa1), 0x75 }, { CCI_REG8(0x5aa2), 0x75 }, ++ { CCI_REG8(0x5aa3), 0x75 }, { CCI_REG8(0x5aa4), 0x75 }, ++ { CCI_REG8(0x5aa5), 0x75 }, { CCI_REG8(0x5aa6), 0x75 }, ++ { CCI_REG8(0x5aa7), 0x75 }, { CCI_REG8(0x5aa8), 0x75 }, ++ { CCI_REG8(0x5aa9), 0x75 }, { CCI_REG8(0x5aaa), 0x75 }, ++ { CCI_REG8(0x5aab), 0x75 }, { CCI_REG8(0x5aac), 0x75 }, ++ { CCI_REG8(0x5aad), 0x75 }, { CCI_REG8(0x5aae), 0x75 }, ++ { CCI_REG8(0x5aaf), 0x75 }, { CCI_REG8(0x5ab0), 0x75 }, ++ { CCI_REG8(0x5ab1), 0x75 }, { CCI_REG8(0x5ab2), 0x75 }, ++ { CCI_REG8(0x5ab3), 0x75 }, { CCI_REG8(0x5ab4), 0x75 }, ++ { CCI_REG8(0x5ab5), 0x75 }, { CCI_REG8(0x5ab6), 0x75 }, ++ { CCI_REG8(0x5ab7), 0x75 }, { CCI_REG8(0x5ab8), 0x75 }, ++ { CCI_REG8(0x5ab9), 0x75 }, { CCI_REG8(0x5aba), 0x75 }, ++ { CCI_REG8(0x5abb), 0x75 }, { CCI_REG8(0x5abc), 0x75 }, ++ { CCI_REG8(0x5abd), 0x75 }, { CCI_REG8(0x5abe), 0x75 }, ++ { CCI_REG8(0x5abf), 0x75 }, { CCI_REG8(0x5ac0), 0x75 }, ++ { CCI_REG8(0x5ac1), 0x75 }, { CCI_REG8(0x5ac2), 0x75 }, ++ { CCI_REG8(0x5ac3), 0x75 }, { CCI_REG8(0x5ac4), 0x75 }, ++ { CCI_REG8(0x5ac5), 0x75 }, { CCI_REG8(0x5ac6), 0x75 }, ++ { CCI_REG8(0x5ac7), 0x75 }, { CCI_REG8(0x5ac8), 0x75 }, ++ { CCI_REG8(0x5ac9), 0x75 }, { CCI_REG8(0x5aca), 0x75 }, ++ { CCI_REG8(0x5acb), 0x75 }, { CCI_REG8(0x5acc), 0x75 }, ++ { CCI_REG8(0x5acd), 0x75 }, { CCI_REG8(0x5ace), 0x75 }, ++ { CCI_REG8(0x5acf), 0x75 }, { CCI_REG8(0x5ad0), 0x75 }, ++ { CCI_REG8(0x5ad1), 0x75 }, { CCI_REG8(0x5ad2), 0x75 }, ++ { CCI_REG8(0x5ad3), 0x75 }, { CCI_REG8(0x5ad4), 0x75 }, ++ { CCI_REG8(0x5ad5), 0x75 }, { CCI_REG8(0x5ad6), 0x75 }, ++ { CCI_REG8(0x5ad7), 0x75 }, { CCI_REG8(0x5ad8), 0x75 }, ++ { CCI_REG8(0x5ad9), 0x75 }, { CCI_REG8(0x5ada), 0x75 }, ++ { CCI_REG8(0x5adb), 0x75 }, { CCI_REG8(0x5adc), 0x75 }, ++ { CCI_REG8(0x5add), 0x75 }, { CCI_REG8(0x5ade), 0x75 }, ++ { CCI_REG8(0x5adf), 0x75 }, { CCI_REG8(0x5ae0), 0x75 }, ++ { CCI_REG8(0x5ae1), 0x75 }, { CCI_REG8(0x5ae2), 0x75 }, ++ { CCI_REG8(0x5ae3), 0x75 }, { CCI_REG8(0x5ae4), 0x75 }, ++ { CCI_REG8(0x5ae5), 0x75 }, { CCI_REG8(0x5ae6), 0x75 }, ++ { CCI_REG8(0x5ae7), 0x75 }, { CCI_REG8(0x5ae8), 0x75 }, ++ { CCI_REG8(0x5ae9), 0x75 }, { CCI_REG8(0x5aea), 0x75 }, ++ { CCI_REG8(0x5aeb), 0x75 }, { CCI_REG8(0x5aec), 0x75 }, ++ { CCI_REG8(0x5aed), 0x75 }, { CCI_REG8(0x5aee), 0x75 }, ++ { CCI_REG8(0x5aef), 0x75 }, { CCI_REG8(0x5af0), 0x75 }, ++ { CCI_REG8(0x5af1), 0x75 }, { CCI_REG8(0x5af2), 0x75 }, ++ { CCI_REG8(0x5af3), 0x75 }, { CCI_REG8(0x5af4), 0x75 }, ++ { CCI_REG8(0x5af5), 0x75 }, { CCI_REG8(0x5af6), 0x75 }, ++ { CCI_REG8(0x5af7), 0x75 }, { CCI_REG8(0x5af8), 0x75 }, ++ { CCI_REG8(0x5af9), 0x75 }, { CCI_REG8(0x5afa), 0x75 }, ++ { CCI_REG8(0x5afb), 0x75 }, { CCI_REG8(0x5afc), 0x75 }, ++ { CCI_REG8(0x5afd), 0x75 }, { CCI_REG8(0x5afe), 0x75 }, ++ { CCI_REG8(0x5aff), 0x75 }, { CCI_REG8(0x5b00), 0x75 }, ++ { CCI_REG8(0x5b01), 0x75 }, { CCI_REG8(0x5b02), 0x75 }, ++ { CCI_REG8(0x5b03), 0x75 }, { CCI_REG8(0x5b04), 0x75 }, ++ { CCI_REG8(0x5b05), 0x75 }, { CCI_REG8(0x5b06), 0x75 }, ++ { CCI_REG8(0x5b07), 0x75 }, { CCI_REG8(0x5b08), 0x75 }, ++ { CCI_REG8(0x5b09), 0x75 }, { CCI_REG8(0x5b0a), 0x75 }, ++ { CCI_REG8(0x5b0b), 0x75 }, { CCI_REG8(0x5b0c), 0x75 }, ++ { CCI_REG8(0x5b0d), 0x75 }, { CCI_REG8(0x5b0e), 0x75 }, ++ { CCI_REG8(0x5b0f), 0x75 }, { CCI_REG8(0x5b10), 0x75 }, ++ { CCI_REG8(0x5b11), 0x75 }, { CCI_REG8(0x5b12), 0x75 }, ++ { CCI_REG8(0x5b13), 0x75 }, { CCI_REG8(0x5b14), 0x75 }, ++ { CCI_REG8(0x5b15), 0x75 }, { CCI_REG8(0x5b16), 0x75 }, ++ { CCI_REG8(0x5b17), 0x75 }, { CCI_REG8(0x5b18), 0x75 }, ++ { CCI_REG8(0x5b19), 0x75 }, { CCI_REG8(0x5b1a), 0x75 }, ++ { CCI_REG8(0x5b1b), 0x75 }, { CCI_REG8(0x5b1c), 0x75 }, ++ { CCI_REG8(0x5b1d), 0x75 }, { CCI_REG8(0x5b1e), 0x75 }, ++ { CCI_REG8(0x5b1f), 0x75 }, { CCI_REG8(0x5b20), 0x75 }, ++ { CCI_REG8(0x5b21), 0x75 }, { CCI_REG8(0x5b22), 0x75 }, ++ { CCI_REG8(0x5b23), 0x75 }, { CCI_REG8(0x5b24), 0x75 }, ++ { CCI_REG8(0x5b25), 0x75 }, { CCI_REG8(0x5b26), 0x75 }, ++ { CCI_REG8(0x5b27), 0x75 }, { CCI_REG8(0x5b28), 0x75 }, ++ { CCI_REG8(0x5b29), 0x75 }, { CCI_REG8(0x5b2a), 0x75 }, ++ { CCI_REG8(0x5b2b), 0x75 }, { CCI_REG8(0x5b2c), 0x75 }, ++ { CCI_REG8(0x5b2d), 0x75 }, { CCI_REG8(0x5b2e), 0x75 }, ++ { CCI_REG8(0x5b2f), 0x75 }, { CCI_REG8(0x5b30), 0x75 }, ++ { CCI_REG8(0x5b31), 0x75 }, { CCI_REG8(0x5b32), 0x75 }, ++ { CCI_REG8(0x5b33), 0x75 }, { CCI_REG8(0x5b34), 0x75 }, ++ { CCI_REG8(0x5b35), 0x75 }, { CCI_REG8(0x5b36), 0x75 }, ++ { CCI_REG8(0x5b37), 0x75 }, { CCI_REG8(0x5b38), 0x75 }, ++ { CCI_REG8(0x5b39), 0x75 }, { CCI_REG8(0x5b3a), 0x75 }, ++ { CCI_REG8(0x5b3b), 0x75 }, { CCI_REG8(0x5b3c), 0x75 }, ++ { CCI_REG8(0x5b3d), 0x75 }, { CCI_REG8(0x5b3e), 0x75 }, ++ { CCI_REG8(0x5b3f), 0x75 }, { CCI_REG8(0x5b40), 0x75 }, ++ { CCI_REG8(0x5b41), 0x75 }, { CCI_REG8(0x5b42), 0x75 }, ++ { CCI_REG8(0x5b43), 0x75 }, { CCI_REG8(0x5b44), 0x75 }, ++ { CCI_REG8(0x5b45), 0x75 }, { CCI_REG8(0x5b46), 0x75 }, ++ { CCI_REG8(0x5b47), 0x75 }, { CCI_REG8(0x5b48), 0x75 }, ++ { CCI_REG8(0x5b49), 0x75 }, { CCI_REG8(0x5b4a), 0x75 }, ++ { CCI_REG8(0x5b4b), 0x75 }, { CCI_REG8(0x5b4c), 0x75 }, ++ { CCI_REG8(0x5b4d), 0x75 }, { CCI_REG8(0x5b4e), 0x75 }, ++ { CCI_REG8(0x5b4f), 0x75 }, { CCI_REG8(0x5b50), 0x75 }, ++ { CCI_REG8(0x5b51), 0x75 }, { CCI_REG8(0x5b52), 0x75 }, ++ { CCI_REG8(0x5b53), 0x75 }, { CCI_REG8(0x5b54), 0x75 }, ++ { CCI_REG8(0x5b55), 0x75 }, { CCI_REG8(0x5b56), 0x75 }, ++ { CCI_REG8(0x5b57), 0x75 }, { CCI_REG8(0x5b58), 0x75 }, ++ { CCI_REG8(0x5b59), 0x75 }, { CCI_REG8(0x5b5a), 0x75 }, ++ { CCI_REG8(0x5b5b), 0x75 }, { CCI_REG8(0x5b5c), 0x75 }, ++ { CCI_REG8(0x5b5d), 0x75 }, { CCI_REG8(0x5b5e), 0x75 }, ++ { CCI_REG8(0x5b5f), 0x75 }, { CCI_REG8(0x5b80), 0x75 }, ++ { CCI_REG8(0x5b81), 0x75 }, { CCI_REG8(0x5b82), 0x75 }, ++ { CCI_REG8(0x5b83), 0x75 }, { CCI_REG8(0x5b84), 0x75 }, ++ { CCI_REG8(0x5b85), 0x75 }, { CCI_REG8(0x5b86), 0x75 }, ++ { CCI_REG8(0x5b87), 0x75 }, { CCI_REG8(0x5b88), 0x75 }, ++ { CCI_REG8(0x5b89), 0x75 }, { CCI_REG8(0x5b8a), 0x75 }, ++ { CCI_REG8(0x5b8b), 0x75 }, { CCI_REG8(0x5b8c), 0x75 }, ++ { CCI_REG8(0x5b8d), 0x75 }, { CCI_REG8(0x5b8e), 0x75 }, ++ { CCI_REG8(0x5b8f), 0x75 }, { CCI_REG8(0x5b90), 0x75 }, ++ { CCI_REG8(0x5b91), 0x75 }, { CCI_REG8(0x5b92), 0x75 }, ++ { CCI_REG8(0x5b93), 0x75 }, { CCI_REG8(0x5b94), 0x75 }, ++ { CCI_REG8(0x5b95), 0x75 }, { CCI_REG8(0x5b96), 0x75 }, ++ { CCI_REG8(0x5b97), 0x75 }, { CCI_REG8(0x5b98), 0x75 }, ++ { CCI_REG8(0x5b99), 0x75 }, { CCI_REG8(0x5b9a), 0x75 }, ++ { CCI_REG8(0x5b9b), 0x75 }, { CCI_REG8(0x5b9c), 0x75 }, ++ { CCI_REG8(0x5b9d), 0x75 }, { CCI_REG8(0x5b9e), 0x75 }, ++ { CCI_REG8(0x5b9f), 0x75 }, { CCI_REG8(0x5ba0), 0x75 }, ++ { CCI_REG8(0x5ba1), 0x75 }, { CCI_REG8(0x5ba2), 0x75 }, ++ { CCI_REG8(0x5ba3), 0x75 }, { CCI_REG8(0x5ba4), 0x75 }, ++ { CCI_REG8(0x5ba5), 0x75 }, { CCI_REG8(0x5ba6), 0x75 }, ++ { CCI_REG8(0x5ba7), 0x75 }, { CCI_REG8(0x5ba8), 0x75 }, ++ { CCI_REG8(0x5ba9), 0x75 }, { CCI_REG8(0x5baa), 0x75 }, ++ { CCI_REG8(0x5bab), 0x75 }, { CCI_REG8(0x5bac), 0x75 }, ++ { CCI_REG8(0x5bad), 0x75 }, { CCI_REG8(0x5bae), 0x75 }, ++ { CCI_REG8(0x5baf), 0x75 }, { CCI_REG8(0x5bb0), 0x75 }, ++ { CCI_REG8(0x5bb1), 0x75 }, { CCI_REG8(0x5bb2), 0x75 }, ++ { CCI_REG8(0x5bb3), 0x75 }, { CCI_REG8(0x5bb4), 0x75 }, ++ { CCI_REG8(0x5bb5), 0x75 }, { CCI_REG8(0x5bb6), 0x75 }, ++ { CCI_REG8(0x5bb7), 0x75 }, { CCI_REG8(0x5bb8), 0x75 }, ++ { CCI_REG8(0x5bb9), 0x75 }, { CCI_REG8(0x5bba), 0x75 }, ++ { CCI_REG8(0x5bbb), 0x75 }, { CCI_REG8(0x5bbc), 0x75 }, ++ { CCI_REG8(0x5bbd), 0x75 }, { CCI_REG8(0x5bbe), 0x75 }, ++ { CCI_REG8(0x5bbf), 0x75 }, { CCI_REG8(0x5bc0), 0x75 }, ++ { CCI_REG8(0x5bc1), 0x75 }, { CCI_REG8(0x5bc2), 0x75 }, ++ { CCI_REG8(0x5bc3), 0x75 }, { CCI_REG8(0x5bc4), 0x75 }, ++ { CCI_REG8(0x5bc5), 0x75 }, { CCI_REG8(0x5bc6), 0x75 }, ++ { CCI_REG8(0x5bc7), 0x75 }, { CCI_REG8(0x5bc8), 0x75 }, ++ { CCI_REG8(0x5bc9), 0x75 }, { CCI_REG8(0x5bca), 0x75 }, ++ { CCI_REG8(0x5bcb), 0x75 }, { CCI_REG8(0x5bcc), 0x75 }, ++ { CCI_REG8(0x5bcd), 0x75 }, { CCI_REG8(0x5bce), 0x75 }, ++ { CCI_REG8(0x5bcf), 0x75 }, { CCI_REG8(0x5bd0), 0x75 }, ++ { CCI_REG8(0x5bd1), 0x75 }, { CCI_REG8(0x5bd2), 0x75 }, ++ { CCI_REG8(0x5bd3), 0x75 }, { CCI_REG8(0x5bd4), 0x75 }, ++ { CCI_REG8(0x5bd5), 0x75 }, { CCI_REG8(0x5bd6), 0x75 }, ++ { CCI_REG8(0x5bd7), 0x75 }, { CCI_REG8(0x5bd8), 0x75 }, ++ { CCI_REG8(0x5bd9), 0x75 }, { CCI_REG8(0x5bda), 0x75 }, ++ { CCI_REG8(0x5bdb), 0x75 }, { CCI_REG8(0x5bdc), 0x75 }, ++ { CCI_REG8(0x5bdd), 0x75 }, { CCI_REG8(0x5bde), 0x75 }, ++ { CCI_REG8(0x5bdf), 0x75 }, { CCI_REG8(0x5be0), 0x75 }, ++ { CCI_REG8(0x5be1), 0x75 }, { CCI_REG8(0x5be2), 0x75 }, ++ { CCI_REG8(0x5be3), 0x75 }, { CCI_REG8(0x5be4), 0x75 }, ++ { CCI_REG8(0x5be5), 0x75 }, { CCI_REG8(0x5be6), 0x75 }, ++ { CCI_REG8(0x5be7), 0x75 }, { CCI_REG8(0x5be8), 0x75 }, ++ { CCI_REG8(0x5be9), 0x75 }, { CCI_REG8(0x5bea), 0x75 }, ++ { CCI_REG8(0x5beb), 0x75 }, { CCI_REG8(0x5bec), 0x75 }, ++ { CCI_REG8(0x5bed), 0x75 }, { CCI_REG8(0x5bee), 0x75 }, ++ { CCI_REG8(0x5bef), 0x75 }, { CCI_REG8(0x5bf0), 0x75 }, ++ { CCI_REG8(0x5bf1), 0x75 }, { CCI_REG8(0x5bf2), 0x75 }, ++ { CCI_REG8(0x5bf3), 0x75 }, { CCI_REG8(0x5bf4), 0x75 }, ++ { CCI_REG8(0x5bf5), 0x75 }, { CCI_REG8(0x5bf6), 0x75 }, ++ { CCI_REG8(0x5bf7), 0x75 }, { CCI_REG8(0x5bf8), 0x75 }, ++ { CCI_REG8(0x5bf9), 0x75 }, { CCI_REG8(0x5bfa), 0x75 }, ++ { CCI_REG8(0x5bfb), 0x75 }, { CCI_REG8(0x5bfc), 0x75 }, ++ { CCI_REG8(0x5bfd), 0x75 }, { CCI_REG8(0x5bfe), 0x75 }, ++ { CCI_REG8(0x5bff), 0x75 }, { CCI_REG8(0x5c00), 0x75 }, ++ { CCI_REG8(0x5c01), 0x75 }, { CCI_REG8(0x5c02), 0x75 }, ++ { CCI_REG8(0x5c03), 0x75 }, { CCI_REG8(0x5c04), 0x75 }, ++ { CCI_REG8(0x5c05), 0x75 }, { CCI_REG8(0x5c06), 0x75 }, ++ { CCI_REG8(0x5c07), 0x75 }, { CCI_REG8(0x5c08), 0x75 }, ++ { CCI_REG8(0x5c09), 0x75 }, { CCI_REG8(0x5c0a), 0x75 }, ++ { CCI_REG8(0x5c0b), 0x75 }, { CCI_REG8(0x5c0c), 0x75 }, ++ { CCI_REG8(0x5c0d), 0x75 }, { CCI_REG8(0x5c0e), 0x75 }, ++ { CCI_REG8(0x5c0f), 0x75 }, { CCI_REG8(0x5c10), 0x75 }, ++ { CCI_REG8(0x5c11), 0x75 }, { CCI_REG8(0x5c12), 0x75 }, ++ { CCI_REG8(0x5c13), 0x75 }, { CCI_REG8(0x5c14), 0x75 }, ++ { CCI_REG8(0x5c15), 0x75 }, { CCI_REG8(0x5c16), 0x75 }, ++ { CCI_REG8(0x5c17), 0x75 }, { CCI_REG8(0x5c18), 0x75 }, ++ { CCI_REG8(0x5c19), 0x75 }, { CCI_REG8(0x5c1a), 0x75 }, ++ { CCI_REG8(0x5c1b), 0x75 }, { CCI_REG8(0x5c1c), 0x75 }, ++ { CCI_REG8(0x5c1d), 0x75 }, { CCI_REG8(0x5c1e), 0x75 }, ++ { CCI_REG8(0x5c1f), 0x75 }, { CCI_REG8(0x5c20), 0x75 }, ++ { CCI_REG8(0x5c21), 0x75 }, { CCI_REG8(0x5c22), 0x75 }, ++ { CCI_REG8(0x5c23), 0x75 }, { CCI_REG8(0x5c24), 0x75 }, ++ { CCI_REG8(0x5c25), 0x75 }, { CCI_REG8(0x5c26), 0x75 }, ++ { CCI_REG8(0x5c27), 0x75 }, { CCI_REG8(0x5c28), 0x75 }, ++ { CCI_REG8(0x5c29), 0x75 }, { CCI_REG8(0x5c2a), 0x75 }, ++ { CCI_REG8(0x5c2b), 0x75 }, { CCI_REG8(0x5c2c), 0x75 }, ++ { CCI_REG8(0x5c2d), 0x75 }, { CCI_REG8(0x5c2e), 0x75 }, ++ { CCI_REG8(0x5c2f), 0x75 }, { CCI_REG8(0x5c30), 0x75 }, ++ { CCI_REG8(0x5c31), 0x75 }, { CCI_REG8(0x5c32), 0x75 }, ++ { CCI_REG8(0x5c33), 0x75 }, { CCI_REG8(0x5c34), 0x75 }, ++ { CCI_REG8(0x5c35), 0x75 }, { CCI_REG8(0x5c36), 0x75 }, ++ { CCI_REG8(0x5c37), 0x75 }, { CCI_REG8(0x5c38), 0x75 }, ++ { CCI_REG8(0x5c39), 0x75 }, { CCI_REG8(0x5c3a), 0x75 }, ++ { CCI_REG8(0x5c3b), 0x75 }, { CCI_REG8(0x5c3c), 0x75 }, ++ { CCI_REG8(0x5c3d), 0x75 }, { CCI_REG8(0x5c3e), 0x75 }, ++ { CCI_REG8(0x5c3f), 0x75 }, { CCI_REG8(0x5c40), 0x75 }, ++ { CCI_REG8(0x5c41), 0x75 }, { CCI_REG8(0x5c42), 0x75 }, ++ { CCI_REG8(0x5c43), 0x75 }, { CCI_REG8(0x5c44), 0x75 }, ++ { CCI_REG8(0x5c45), 0x75 }, { CCI_REG8(0x5c46), 0x75 }, ++ { CCI_REG8(0x5c47), 0x75 }, { CCI_REG8(0x5c48), 0x75 }, ++ { CCI_REG8(0x5c49), 0x75 }, { CCI_REG8(0x5c4a), 0x75 }, ++ { CCI_REG8(0x5c4b), 0x75 }, { CCI_REG8(0x5c4c), 0x75 }, ++ { CCI_REG8(0x5c4d), 0x75 }, { CCI_REG8(0x5c4e), 0x75 }, ++ { CCI_REG8(0x5c4f), 0x75 }, { CCI_REG8(0x5c50), 0x75 }, ++ { CCI_REG8(0x5c51), 0x75 }, { CCI_REG8(0x5c52), 0x75 }, ++ { CCI_REG8(0x5c53), 0x75 }, { CCI_REG8(0x5c54), 0x75 }, ++ { CCI_REG8(0x5c55), 0x75 }, { CCI_REG8(0x5c56), 0x75 }, ++ { CCI_REG8(0x5c57), 0x75 }, { CCI_REG8(0x5c58), 0x75 }, ++ { CCI_REG8(0x5c59), 0x75 }, { CCI_REG8(0x5c5a), 0x75 }, ++ { CCI_REG8(0x5c5b), 0x75 }, { CCI_REG8(0x5c5c), 0x75 }, ++ { CCI_REG8(0x5c5d), 0x75 }, { CCI_REG8(0x5c5e), 0x75 }, ++ { CCI_REG8(0x5c5f), 0x75 }, { CCI_REG8(0x5c60), 0x75 }, ++ { CCI_REG8(0x5c61), 0x75 }, { CCI_REG8(0x5c62), 0x75 }, ++ { CCI_REG8(0x5c63), 0x75 }, { CCI_REG8(0x5c64), 0x75 }, ++ { CCI_REG8(0x5c65), 0x75 }, { CCI_REG8(0x5c66), 0x75 }, ++ { CCI_REG8(0x5c67), 0x75 }, { CCI_REG8(0x5c68), 0x75 }, ++ { CCI_REG8(0x5c69), 0x75 }, { CCI_REG8(0x5c6a), 0x75 }, ++ { CCI_REG8(0x5c6b), 0x75 }, { CCI_REG8(0x5c6c), 0x75 }, ++ { CCI_REG8(0x5c6d), 0x75 }, { CCI_REG8(0x5c6e), 0x75 }, ++ { CCI_REG8(0x5c6f), 0x75 }, { CCI_REG8(0x5c70), 0x75 }, ++ { CCI_REG8(0x5c71), 0x75 }, { CCI_REG8(0x5c72), 0x75 }, ++ { CCI_REG8(0x5c73), 0x75 }, { CCI_REG8(0x5c74), 0x75 }, ++ { CCI_REG8(0x5c75), 0x75 }, { CCI_REG8(0x5c76), 0x75 }, ++ { CCI_REG8(0x5c77), 0x75 }, { CCI_REG8(0x5c78), 0x75 }, ++ { CCI_REG8(0x5c79), 0x75 }, { CCI_REG8(0x5c7a), 0x75 }, ++ { CCI_REG8(0x5c7b), 0x75 }, { CCI_REG8(0x5c7c), 0x75 }, ++ { CCI_REG8(0x5c7d), 0x75 }, { CCI_REG8(0x5c7e), 0x75 }, ++ { CCI_REG8(0x5c7f), 0x75 }, { CCI_REG8(0x5c80), 0x75 }, ++ { CCI_REG8(0x5c81), 0x75 }, { CCI_REG8(0x5c82), 0x75 }, ++ { CCI_REG8(0x5c83), 0x75 }, { CCI_REG8(0x5c84), 0x75 }, ++ { CCI_REG8(0x5c85), 0x75 }, { CCI_REG8(0x5c86), 0x75 }, ++ { CCI_REG8(0x5c87), 0x75 }, { CCI_REG8(0x5c88), 0x75 }, ++ { CCI_REG8(0x5c89), 0x75 }, { CCI_REG8(0x5c8a), 0x75 }, ++ { CCI_REG8(0x5c8b), 0x75 }, { CCI_REG8(0x5c8c), 0x75 }, ++ { CCI_REG8(0x5c8d), 0x75 }, { CCI_REG8(0x5c8e), 0x75 }, ++ { CCI_REG8(0x5c8f), 0x75 }, { CCI_REG8(0x5c90), 0x75 }, ++ { CCI_REG8(0x5c91), 0x75 }, { CCI_REG8(0x5c92), 0x75 }, ++ { CCI_REG8(0x5c93), 0x75 }, { CCI_REG8(0x5c94), 0x75 }, ++ { CCI_REG8(0x5c95), 0x75 }, { CCI_REG8(0x5c96), 0x75 }, ++ { CCI_REG8(0x5c97), 0x75 }, { CCI_REG8(0x5c98), 0x75 }, ++ { CCI_REG8(0x5c99), 0x75 }, { CCI_REG8(0x5c9a), 0x75 }, ++ { CCI_REG8(0x5c9b), 0x75 }, { CCI_REG8(0x5c9c), 0x75 }, ++ { CCI_REG8(0x5c9d), 0x75 }, { CCI_REG8(0x5c9e), 0x75 }, ++ { CCI_REG8(0x5c9f), 0x75 }, { CCI_REG8(0x5ca0), 0x75 }, ++ { CCI_REG8(0x5ca1), 0x75 }, { CCI_REG8(0x5ca2), 0x75 }, ++ { CCI_REG8(0x5ca3), 0x75 }, { CCI_REG8(0x5ca4), 0x75 }, ++ { CCI_REG8(0x5ca5), 0x75 }, { CCI_REG8(0x5ca6), 0x75 }, ++ { CCI_REG8(0x5ca7), 0x75 }, { CCI_REG8(0x5ca8), 0x75 }, ++ { CCI_REG8(0x5ca9), 0x75 }, { CCI_REG8(0x5caa), 0x75 }, ++ { CCI_REG8(0x5cab), 0x75 }, { CCI_REG8(0x5cac), 0x75 }, ++ { CCI_REG8(0x5cad), 0x75 }, { CCI_REG8(0x5cae), 0x75 }, ++ { CCI_REG8(0x5caf), 0x75 }, { CCI_REG8(0x5cb0), 0x75 }, ++ { CCI_REG8(0x5cb1), 0x75 }, { CCI_REG8(0x5cb2), 0x75 }, ++ { CCI_REG8(0x5cb3), 0x75 }, { CCI_REG8(0x5cb4), 0x75 }, ++ { CCI_REG8(0x5cb5), 0x75 }, { CCI_REG8(0x5cb6), 0x75 }, ++ { CCI_REG8(0x5cb7), 0x75 }, { CCI_REG8(0x5cb8), 0x75 }, ++ { CCI_REG8(0x5cb9), 0x75 }, { CCI_REG8(0x5cba), 0x75 }, ++ { CCI_REG8(0x5cbb), 0x75 }, { CCI_REG8(0x5cbc), 0x75 }, ++ { CCI_REG8(0x5cbd), 0x75 }, { CCI_REG8(0x5cbe), 0x75 }, ++ { CCI_REG8(0x5cbf), 0x75 }, { CCI_REG8(0x5cc0), 0x75 }, ++ { CCI_REG8(0x5cc1), 0x75 }, { CCI_REG8(0x5cc2), 0x75 }, ++ { CCI_REG8(0x5cc3), 0x75 }, { CCI_REG8(0x5cc4), 0x75 }, ++ { CCI_REG8(0x5cc5), 0x75 }, { CCI_REG8(0x5cc6), 0x75 }, ++ { CCI_REG8(0x5cc7), 0x75 }, { CCI_REG8(0x5cc8), 0x75 }, ++ { CCI_REG8(0x5cc9), 0x75 }, { CCI_REG8(0x5cca), 0x75 }, ++ { CCI_REG8(0x5ccb), 0x75 }, { CCI_REG8(0x5ccc), 0x75 }, ++ { CCI_REG8(0x5ccd), 0x75 }, { CCI_REG8(0x5cce), 0x75 }, ++ { CCI_REG8(0x5ccf), 0x75 }, { CCI_REG8(0x5cd0), 0x75 }, ++ { CCI_REG8(0x5cd1), 0x75 }, { CCI_REG8(0x5cd2), 0x75 }, ++ { CCI_REG8(0x5cd3), 0x75 }, { CCI_REG8(0x5cd4), 0x75 }, ++ { CCI_REG8(0x5cd5), 0x75 }, { CCI_REG8(0x5cd6), 0x75 }, ++ { CCI_REG8(0x5cd7), 0x75 }, { CCI_REG8(0x5cd8), 0x75 }, ++ { CCI_REG8(0x5cd9), 0x75 }, { CCI_REG8(0x5cda), 0x75 }, ++ { CCI_REG8(0x5cdb), 0x75 }, { CCI_REG8(0x5cdc), 0x75 }, ++ { CCI_REG8(0x5cdd), 0x75 }, { CCI_REG8(0x5cde), 0x75 }, ++ { CCI_REG8(0x5cdf), 0x75 }, { CCI_REG8(0x5ce0), 0x75 }, ++ { CCI_REG8(0x5ce1), 0x75 }, { CCI_REG8(0x5ce2), 0x75 }, ++ { CCI_REG8(0x5ce3), 0x75 }, { CCI_REG8(0x5ce4), 0x75 }, ++ { CCI_REG8(0x5ce5), 0x75 }, { CCI_REG8(0x5ce6), 0x75 }, ++ { CCI_REG8(0x5ce7), 0x75 }, { CCI_REG8(0x5ce8), 0x75 }, ++ { CCI_REG8(0x5ce9), 0x75 }, { CCI_REG8(0x5cea), 0x75 }, ++ { CCI_REG8(0x5ceb), 0x75 }, { CCI_REG8(0x5cec), 0x75 }, ++ { CCI_REG8(0x5ced), 0x75 }, { CCI_REG8(0x5cee), 0x75 }, ++ { CCI_REG8(0x5cef), 0x75 }, { CCI_REG8(0x5cf0), 0x75 }, ++ { CCI_REG8(0x5cf1), 0x75 }, { CCI_REG8(0x5cf2), 0x75 }, ++ { CCI_REG8(0x5cf3), 0x75 }, { CCI_REG8(0x5cf4), 0x75 }, ++ { CCI_REG8(0x5cf5), 0x75 }, { CCI_REG8(0x5cf6), 0x75 }, ++ { CCI_REG8(0x5cf7), 0x75 }, { CCI_REG8(0x5cf8), 0x75 }, ++ { CCI_REG8(0x5cf9), 0x75 }, { CCI_REG8(0x5cfa), 0x75 }, ++ { CCI_REG8(0x5cfb), 0x75 }, { CCI_REG8(0x5cfc), 0x75 }, ++ { CCI_REG8(0x5cfd), 0x75 }, { CCI_REG8(0x5cfe), 0x75 }, ++ { CCI_REG8(0x5cff), 0x75 }, { CCI_REG8(0x5d00), 0x75 }, ++ { CCI_REG8(0x5d01), 0x75 }, { CCI_REG8(0x5d02), 0x75 }, ++ { CCI_REG8(0x5d03), 0x75 }, { CCI_REG8(0x5d04), 0x75 }, ++ { CCI_REG8(0x5d05), 0x75 }, { CCI_REG8(0x5d06), 0x75 }, ++ { CCI_REG8(0x5d07), 0x75 }, { CCI_REG8(0x5d08), 0x75 }, ++ { CCI_REG8(0x5d09), 0x75 }, { CCI_REG8(0x5d0a), 0x75 }, ++ { CCI_REG8(0x5d0b), 0x75 }, { CCI_REG8(0x5d0c), 0x75 }, ++ { CCI_REG8(0x5d0d), 0x75 }, { CCI_REG8(0x5d0e), 0x75 }, ++ { CCI_REG8(0x5d0f), 0x75 }, { CCI_REG8(0x5d10), 0x75 }, ++ { CCI_REG8(0x5d11), 0x75 }, { CCI_REG8(0x5d12), 0x75 }, ++ { CCI_REG8(0x5d13), 0x75 }, { CCI_REG8(0x5d14), 0x75 }, ++ { CCI_REG8(0x5d15), 0x75 }, { CCI_REG8(0x5d16), 0x75 }, ++ { CCI_REG8(0x5d17), 0x75 }, { CCI_REG8(0x5d18), 0x75 }, ++ { CCI_REG8(0x5d19), 0x75 }, { CCI_REG8(0x5d1a), 0x75 }, ++ { CCI_REG8(0x5d1b), 0x75 }, { CCI_REG8(0x5d1c), 0x75 }, ++ { CCI_REG8(0x5d1d), 0x75 }, { CCI_REG8(0x5d1e), 0x75 }, ++ { CCI_REG8(0x5d1f), 0x75 }, { CCI_REG8(0x5d20), 0x75 }, ++ { CCI_REG8(0x5d21), 0x75 }, { CCI_REG8(0x5d22), 0x75 }, ++ { CCI_REG8(0x5d23), 0x75 }, { CCI_REG8(0x5d24), 0x75 }, ++ { CCI_REG8(0x5d25), 0x75 }, { CCI_REG8(0x5d26), 0x75 }, ++ { CCI_REG8(0x5d27), 0x75 }, { CCI_REG8(0x5d28), 0x75 }, ++ { CCI_REG8(0x5d29), 0x75 }, { CCI_REG8(0x5d2a), 0x75 }, ++ { CCI_REG8(0x5d2b), 0x75 }, { CCI_REG8(0x5d2c), 0x75 }, ++ { CCI_REG8(0x5d2d), 0x75 }, { CCI_REG8(0x5d2e), 0x75 }, ++ { CCI_REG8(0x5d2f), 0x75 }, { CCI_REG8(0x5d30), 0x75 }, ++ { CCI_REG8(0x5d31), 0x75 }, { CCI_REG8(0x5d32), 0x75 }, ++ { CCI_REG8(0x5d33), 0x75 }, { CCI_REG8(0x5d34), 0x75 }, ++ { CCI_REG8(0x5d35), 0x75 }, { CCI_REG8(0x5d36), 0x75 }, ++ { CCI_REG8(0x5d37), 0x75 }, { CCI_REG8(0x5d38), 0x75 }, ++ { CCI_REG8(0x5d39), 0x75 }, { CCI_REG8(0x5d3a), 0x75 }, ++ { CCI_REG8(0x5d3b), 0x75 }, { CCI_REG8(0x5d3c), 0x75 }, ++ { CCI_REG8(0x5d3d), 0x75 }, { CCI_REG8(0x5d3e), 0x75 }, ++ { CCI_REG8(0x5d3f), 0x75 }, { CCI_REG8(0x5d40), 0x75 }, ++ { CCI_REG8(0x5d41), 0x75 }, { CCI_REG8(0x5d42), 0x75 }, ++ { CCI_REG8(0x5d43), 0x75 }, { CCI_REG8(0x5d44), 0x75 }, ++ { CCI_REG8(0x5d45), 0x75 }, { CCI_REG8(0x5d46), 0x75 }, ++ { CCI_REG8(0x5d47), 0x75 }, { CCI_REG8(0x5d48), 0x75 }, ++ { CCI_REG8(0x5d49), 0x75 }, { CCI_REG8(0x5d4a), 0x75 }, ++ { CCI_REG8(0x5d4b), 0x75 }, { CCI_REG8(0x5d4c), 0x75 }, ++ { CCI_REG8(0x5d4d), 0x75 }, { CCI_REG8(0x5d4e), 0x75 }, ++ { CCI_REG8(0x5d4f), 0x75 }, { CCI_REG8(0x5d50), 0x75 }, ++ { CCI_REG8(0x5d51), 0x75 }, { CCI_REG8(0x5d52), 0x75 }, ++ { CCI_REG8(0x5d53), 0x75 }, { CCI_REG8(0x5d54), 0x75 }, ++ { CCI_REG8(0x5d55), 0x75 }, { CCI_REG8(0x5d56), 0x75 }, ++ { CCI_REG8(0x5d57), 0x75 }, { CCI_REG8(0x5d58), 0x75 }, ++ { CCI_REG8(0x5d59), 0x75 }, { CCI_REG8(0x5d5a), 0x75 }, ++ { CCI_REG8(0x5d5b), 0x75 }, { CCI_REG8(0x5d5c), 0x75 }, ++ { CCI_REG8(0x5d5d), 0x75 }, { CCI_REG8(0x5d5e), 0x75 }, ++ { CCI_REG8(0x5d5f), 0x75 }, { CCI_REG8(0x5d60), 0x75 }, ++ { CCI_REG8(0x5d61), 0x75 }, { CCI_REG8(0x5d62), 0x75 }, ++ { CCI_REG8(0x5d63), 0x75 }, { CCI_REG8(0x5d64), 0x75 }, ++ { CCI_REG8(0x5d65), 0x75 }, { CCI_REG8(0x5d66), 0x75 }, ++ { CCI_REG8(0x5d67), 0x75 }, { CCI_REG8(0x5d68), 0x75 }, ++ { CCI_REG8(0x5d69), 0x75 }, { CCI_REG8(0x5d6a), 0x75 }, ++ { CCI_REG8(0x5d6b), 0x75 }, { CCI_REG8(0x5d6c), 0x75 }, ++ { CCI_REG8(0x5d6d), 0x75 }, { CCI_REG8(0x5d6e), 0x75 }, ++ { CCI_REG8(0x5d6f), 0x75 }, { CCI_REG8(0x5d70), 0x75 }, ++ { CCI_REG8(0x5d71), 0x75 }, { CCI_REG8(0x5d72), 0x75 }, ++ { CCI_REG8(0x5d73), 0x75 }, { CCI_REG8(0x5d74), 0x75 }, ++ { CCI_REG8(0x5d75), 0x75 }, { CCI_REG8(0x5d76), 0x75 }, ++ { CCI_REG8(0x5d77), 0x75 }, { CCI_REG8(0x5d78), 0x75 }, ++ { CCI_REG8(0x5d79), 0x75 }, { CCI_REG8(0x5d7a), 0x75 }, ++ { CCI_REG8(0x5d7b), 0x75 }, { CCI_REG8(0x5d7c), 0x75 }, ++ { CCI_REG8(0x5d7d), 0x75 }, { CCI_REG8(0x5d7e), 0x75 }, ++ { CCI_REG8(0x5d7f), 0x75 }, { CCI_REG8(0x5d80), 0x75 }, ++ { CCI_REG8(0x5d81), 0x75 }, { CCI_REG8(0x5d82), 0x75 }, ++ { CCI_REG8(0x5d83), 0x75 }, { CCI_REG8(0x5d84), 0x75 }, ++ { CCI_REG8(0x5d85), 0x75 }, { CCI_REG8(0x5d86), 0x75 }, ++ { CCI_REG8(0x5d87), 0x75 }, { CCI_REG8(0x5d88), 0x75 }, ++ { CCI_REG8(0x5d89), 0x75 }, { CCI_REG8(0x5d8a), 0x75 }, ++ { CCI_REG8(0x5d8b), 0x75 }, { CCI_REG8(0x5d8c), 0x75 }, ++ { CCI_REG8(0x5d8d), 0x75 }, { CCI_REG8(0x5d8e), 0x75 }, ++ { CCI_REG8(0x5d8f), 0x75 }, { CCI_REG8(0x5d90), 0x75 }, ++ { CCI_REG8(0x5d91), 0x75 }, { CCI_REG8(0x5d92), 0x75 }, ++ { CCI_REG8(0x5d93), 0x75 }, { CCI_REG8(0x5d94), 0x75 }, ++ { CCI_REG8(0x5d95), 0x75 }, { CCI_REG8(0x5d96), 0x75 }, ++ { CCI_REG8(0x5d97), 0x75 }, { CCI_REG8(0x5d98), 0x75 }, ++ { CCI_REG8(0x5d99), 0x75 }, { CCI_REG8(0x5d9a), 0x75 }, ++ { CCI_REG8(0x5d9b), 0x75 }, { CCI_REG8(0x5d9c), 0x75 }, ++ { CCI_REG8(0x5d9d), 0x75 }, { CCI_REG8(0x5d9e), 0x75 }, ++ { CCI_REG8(0x5d9f), 0x75 }, { CCI_REG8(0x5da0), 0x75 }, ++ { CCI_REG8(0x5da1), 0x75 }, { CCI_REG8(0x5da2), 0x75 }, ++ { CCI_REG8(0x5da3), 0x75 }, { CCI_REG8(0x5da4), 0x75 }, ++ { CCI_REG8(0x5da5), 0x75 }, { CCI_REG8(0x5da6), 0x75 }, ++ { CCI_REG8(0x5da7), 0x75 }, { CCI_REG8(0x5da8), 0x75 }, ++ { CCI_REG8(0x5da9), 0x75 }, { CCI_REG8(0x5daa), 0x75 }, ++ { CCI_REG8(0x5dab), 0x75 }, { CCI_REG8(0x5dac), 0x75 }, ++ { CCI_REG8(0x5dad), 0x75 }, { CCI_REG8(0x5dae), 0x75 }, ++ { CCI_REG8(0x5daf), 0x75 }, { CCI_REG8(0x5db0), 0x75 }, ++ { CCI_REG8(0x5db1), 0x75 }, { CCI_REG8(0x5db2), 0x75 }, ++ { CCI_REG8(0x5db3), 0x75 }, { CCI_REG8(0x5db4), 0x75 }, ++ { CCI_REG8(0x5db5), 0x75 }, { CCI_REG8(0x5db6), 0x75 }, ++ { CCI_REG8(0x5db7), 0x75 }, { CCI_REG8(0x5db8), 0x75 }, ++ { CCI_REG8(0x5db9), 0x75 }, { CCI_REG8(0x5dba), 0x75 }, ++ { CCI_REG8(0x5dbb), 0x75 }, { CCI_REG8(0x5dbc), 0x75 }, ++ { CCI_REG8(0x5dbd), 0x75 }, { CCI_REG8(0x5dbe), 0x75 }, ++ { CCI_REG8(0x5dbf), 0x75 }, { CCI_REG8(0x5dc0), 0x75 }, ++ { CCI_REG8(0x5dc1), 0x75 }, { CCI_REG8(0x5dc2), 0x75 }, ++ { CCI_REG8(0x5dc3), 0x75 }, { CCI_REG8(0x5dc4), 0x75 }, ++ { CCI_REG8(0x5dc5), 0x75 }, { CCI_REG8(0x5dc6), 0x75 }, ++ { CCI_REG8(0x5dc7), 0x75 }, { CCI_REG8(0x5dc8), 0x75 }, ++ { CCI_REG8(0x5dc9), 0x75 }, { CCI_REG8(0x5dca), 0x75 }, ++ { CCI_REG8(0x5dcb), 0x75 }, { CCI_REG8(0x5dcc), 0x75 }, ++ { CCI_REG8(0x5dcd), 0x75 }, { CCI_REG8(0x5dce), 0x75 }, ++ { CCI_REG8(0x5dcf), 0x75 }, { CCI_REG8(0x5dd0), 0x75 }, ++ { CCI_REG8(0x5dd1), 0x75 }, { CCI_REG8(0x5dd2), 0x75 }, ++ { CCI_REG8(0x5dd3), 0x75 }, { CCI_REG8(0x5dd4), 0x75 }, ++ { CCI_REG8(0x5dd5), 0x75 }, { CCI_REG8(0x5dd6), 0x75 }, ++ { CCI_REG8(0x5dd7), 0x75 }, { CCI_REG8(0x5dd8), 0x75 }, ++ { CCI_REG8(0x5dd9), 0x75 }, { CCI_REG8(0x5dda), 0x75 }, ++ { CCI_REG8(0x5ddb), 0x75 }, { CCI_REG8(0x5ddc), 0x75 }, ++ { CCI_REG8(0x5ddd), 0x75 }, { CCI_REG8(0x5dde), 0x75 }, ++ { CCI_REG8(0x5ddf), 0x75 }, { CCI_REG8(0x5de0), 0x75 }, ++ { CCI_REG8(0x5de1), 0x75 }, { CCI_REG8(0x5de2), 0x75 }, ++ { CCI_REG8(0x5de3), 0x75 }, { CCI_REG8(0x5de4), 0x75 }, ++ { CCI_REG8(0x5de5), 0x75 }, { CCI_REG8(0x5de6), 0x75 }, ++ { CCI_REG8(0x5de7), 0x75 }, { CCI_REG8(0x5de8), 0x75 }, ++ { CCI_REG8(0x5de9), 0x75 }, { CCI_REG8(0x5dea), 0x75 }, ++ { CCI_REG8(0x5deb), 0x75 }, { CCI_REG8(0x5dec), 0x75 }, ++ { CCI_REG8(0x5ded), 0x75 }, { CCI_REG8(0x5dee), 0x75 }, ++ { CCI_REG8(0x5def), 0x75 }, { CCI_REG8(0x5df0), 0x75 }, ++ { CCI_REG8(0x5df1), 0x75 }, { CCI_REG8(0x5df2), 0x75 }, ++ { CCI_REG8(0x5df3), 0x75 }, { CCI_REG8(0x5df4), 0x75 }, ++ { CCI_REG8(0x5df5), 0x75 }, { CCI_REG8(0x5df6), 0x75 }, ++ { CCI_REG8(0x5df7), 0x75 }, { CCI_REG8(0x5df8), 0x75 }, ++ { CCI_REG8(0x5df9), 0x75 }, { CCI_REG8(0x5dfa), 0x75 }, ++ { CCI_REG8(0x5dfb), 0x75 }, { CCI_REG8(0x5dfc), 0x75 }, ++ { CCI_REG8(0x5dfd), 0x75 }, { CCI_REG8(0x5dfe), 0x75 }, ++ { CCI_REG8(0x5dff), 0x75 }, { CCI_REG8(0x5e00), 0x75 }, ++ { CCI_REG8(0x5e01), 0x75 }, { CCI_REG8(0x5e02), 0x75 }, ++ { CCI_REG8(0x5e03), 0x75 }, { CCI_REG8(0x5e04), 0x75 }, ++ { CCI_REG8(0x5e05), 0x75 }, { CCI_REG8(0x5e06), 0x75 }, ++ { CCI_REG8(0x5e07), 0x75 }, { CCI_REG8(0x5e08), 0x75 }, ++ { CCI_REG8(0x5e09), 0x75 }, { CCI_REG8(0x5e0a), 0x75 }, ++ { CCI_REG8(0x5e0b), 0x75 }, { CCI_REG8(0x5e0c), 0x75 }, ++ { CCI_REG8(0x5e0d), 0x75 }, { CCI_REG8(0x5e0e), 0x75 }, ++ { CCI_REG8(0x5e0f), 0x75 }, { CCI_REG8(0x5e10), 0x75 }, ++ { CCI_REG8(0x5e11), 0x75 }, { CCI_REG8(0x5e12), 0x75 }, ++ { CCI_REG8(0x5e13), 0x75 }, { CCI_REG8(0x5e14), 0x75 }, ++ { CCI_REG8(0x5e15), 0x75 }, { CCI_REG8(0x5e16), 0x75 }, ++ { CCI_REG8(0x5e17), 0x75 }, { CCI_REG8(0x5e18), 0x75 }, ++ { CCI_REG8(0x5e19), 0x75 }, { CCI_REG8(0x5e1a), 0x75 }, ++ { CCI_REG8(0x5e1b), 0x75 }, { CCI_REG8(0x5e1c), 0x75 }, ++ { CCI_REG8(0x5e1d), 0x75 }, { CCI_REG8(0x5e1e), 0x75 }, ++ { CCI_REG8(0x5e1f), 0x75 }, { CCI_REG8(0x5e20), 0x75 }, ++ { CCI_REG8(0x5e21), 0x75 }, { CCI_REG8(0x5e22), 0x75 }, ++ { CCI_REG8(0x5e23), 0x75 }, { CCI_REG8(0x5e24), 0x75 }, ++ { CCI_REG8(0x5e25), 0x75 }, { CCI_REG8(0x5e26), 0x75 }, ++ { CCI_REG8(0x5e27), 0x75 }, { CCI_REG8(0x5e28), 0x75 }, ++ { CCI_REG8(0x5e29), 0x75 }, { CCI_REG8(0x5e2a), 0x75 }, ++ { CCI_REG8(0x5e2b), 0x75 }, { CCI_REG8(0x5e2c), 0x75 }, ++ { CCI_REG8(0x5e2d), 0x75 }, { CCI_REG8(0x5e2e), 0x75 }, ++ { CCI_REG8(0x5e2f), 0x75 }, { CCI_REG8(0x5e30), 0x75 }, ++ { CCI_REG8(0x5e31), 0x75 }, { CCI_REG8(0x5e32), 0x75 }, ++ { CCI_REG8(0x5e33), 0x75 }, { CCI_REG8(0x5e34), 0x75 }, ++ { CCI_REG8(0x5e35), 0x75 }, { CCI_REG8(0x5e36), 0x75 }, ++ { CCI_REG8(0x5e37), 0x75 }, { CCI_REG8(0x5e38), 0x75 }, ++ { CCI_REG8(0x5e39), 0x75 }, { CCI_REG8(0x5e3a), 0x75 }, ++ { CCI_REG8(0x5e3b), 0x75 }, { CCI_REG8(0x5e3c), 0x75 }, ++ { CCI_REG8(0x5e3d), 0x75 }, { CCI_REG8(0x5e3e), 0x75 }, ++ { CCI_REG8(0x5e3f), 0x75 }, { CCI_REG8(0x5e40), 0x75 }, ++ { CCI_REG8(0x5e41), 0x75 }, { CCI_REG8(0x5e42), 0x75 }, ++ { CCI_REG8(0x5e43), 0x75 }, { CCI_REG8(0x5e44), 0x75 }, ++ { CCI_REG8(0x5e45), 0x75 }, { CCI_REG8(0x5e46), 0x75 }, ++ { CCI_REG8(0x5e47), 0x75 }, { CCI_REG8(0x5e48), 0x75 }, ++ { CCI_REG8(0x5e49), 0x75 }, { CCI_REG8(0x5e4a), 0x75 }, ++ { CCI_REG8(0x5e4b), 0x75 }, { CCI_REG8(0x5e4c), 0x75 }, ++ { CCI_REG8(0x5e4d), 0x75 }, { CCI_REG8(0x5e4e), 0x75 }, ++ { CCI_REG8(0x5e4f), 0x75 }, { CCI_REG8(0x5e50), 0x75 }, ++ { CCI_REG8(0x5e51), 0x75 }, { CCI_REG8(0x5e52), 0x75 }, ++ { CCI_REG8(0x5e53), 0x75 }, { CCI_REG8(0x5e54), 0x75 }, ++ { CCI_REG8(0x5e55), 0x75 }, { CCI_REG8(0x5e56), 0x75 }, ++ { CCI_REG8(0x5e57), 0x75 }, { CCI_REG8(0x5e58), 0x75 }, ++ { CCI_REG8(0x5e59), 0x75 }, { CCI_REG8(0x5e5a), 0x75 }, ++ { CCI_REG8(0x5e5b), 0x75 }, { CCI_REG8(0x5e5c), 0x75 }, ++ { CCI_REG8(0x5e5d), 0x75 }, { CCI_REG8(0x5e5e), 0x75 }, ++ { CCI_REG8(0x5e5f), 0x75 }, { CCI_REG8(0x5e60), 0x75 }, ++ { CCI_REG8(0x5e61), 0x75 }, { CCI_REG8(0x5e62), 0x75 }, ++ { CCI_REG8(0x5e63), 0x75 }, { CCI_REG8(0x5e64), 0x75 }, ++ { CCI_REG8(0x5e65), 0x75 }, { CCI_REG8(0x5e66), 0x75 }, ++ { CCI_REG8(0x5e67), 0x75 }, { CCI_REG8(0x5e68), 0x75 }, ++ { CCI_REG8(0x5e69), 0x75 }, { CCI_REG8(0x5e6a), 0x75 }, ++ { CCI_REG8(0x5e6b), 0x75 }, { CCI_REG8(0x5e6c), 0x75 }, ++ { CCI_REG8(0x5e6d), 0x75 }, { CCI_REG8(0x5e6e), 0x75 }, ++ { CCI_REG8(0x5e6f), 0x75 }, { CCI_REG8(0x5e70), 0x75 }, ++ { CCI_REG8(0x5e71), 0x75 }, { CCI_REG8(0x5e72), 0x75 }, ++ { CCI_REG8(0x5e73), 0x75 }, { CCI_REG8(0x5e74), 0x75 }, ++ { CCI_REG8(0x5e75), 0x75 }, { CCI_REG8(0x5e76), 0x75 }, ++ { CCI_REG8(0x5e77), 0x75 }, { CCI_REG8(0x5e78), 0x75 }, ++ { CCI_REG8(0x5e79), 0x75 }, { CCI_REG8(0x5e7a), 0x75 }, ++ { CCI_REG8(0x5e7b), 0x75 }, { CCI_REG8(0x5e7c), 0x75 }, ++ { CCI_REG8(0x5e7d), 0x75 }, { CCI_REG8(0x5e7e), 0x75 }, ++ { CCI_REG8(0x5e7f), 0x75 }, { CCI_REG8(0x5e80), 0x75 }, ++ { CCI_REG8(0x5e81), 0x75 }, { CCI_REG8(0x5e82), 0x75 }, ++ { CCI_REG8(0x5e83), 0x75 }, { CCI_REG8(0x5e84), 0x75 }, ++ { CCI_REG8(0x5e85), 0x75 }, { CCI_REG8(0x5e86), 0x75 }, ++ { CCI_REG8(0x5e87), 0x75 }, { CCI_REG8(0x5e88), 0x75 }, ++ { CCI_REG8(0x5e89), 0x75 }, { CCI_REG8(0x5e8a), 0x75 }, ++ { CCI_REG8(0x5e8b), 0x75 }, { CCI_REG8(0x5e8c), 0x75 }, ++ { CCI_REG8(0x5e8d), 0x75 }, { CCI_REG8(0x5e8e), 0x75 }, ++ { CCI_REG8(0x5e8f), 0x75 }, { CCI_REG8(0x5e90), 0x75 }, ++ { CCI_REG8(0x5e91), 0x75 }, { CCI_REG8(0x5e92), 0x75 }, ++ { CCI_REG8(0x5e93), 0x75 }, { CCI_REG8(0x5e94), 0x75 }, ++ { CCI_REG8(0x5e95), 0x75 }, { CCI_REG8(0x5e96), 0x75 }, ++ { CCI_REG8(0x5e97), 0x75 }, { CCI_REG8(0x5e98), 0x75 }, ++ { CCI_REG8(0x5e99), 0x75 }, { CCI_REG8(0x5e9a), 0x75 }, ++ { CCI_REG8(0x5e9b), 0x75 }, { CCI_REG8(0x5e9c), 0x75 }, ++ { CCI_REG8(0x5e9d), 0x75 }, { CCI_REG8(0x5e9e), 0x75 }, ++ { CCI_REG8(0x5e9f), 0x75 }, { CCI_REG8(0x5ea0), 0x75 }, ++ { CCI_REG8(0x5ea1), 0x75 }, { CCI_REG8(0x5ea2), 0x75 }, ++ { CCI_REG8(0x5ea3), 0x75 }, { CCI_REG8(0x5ea4), 0x75 }, ++ { CCI_REG8(0x5ea5), 0x75 }, { CCI_REG8(0x5ea6), 0x75 }, ++ { CCI_REG8(0x5ea7), 0x75 }, { CCI_REG8(0x5ea8), 0x75 }, ++ { CCI_REG8(0x5ea9), 0x75 }, { CCI_REG8(0x5eaa), 0x75 }, ++ { CCI_REG8(0x5eab), 0x75 }, { CCI_REG8(0x5eac), 0x75 }, ++ { CCI_REG8(0x5ead), 0x75 }, { CCI_REG8(0x5eae), 0x75 }, ++ { CCI_REG8(0x5eaf), 0x75 }, { CCI_REG8(0x5eb0), 0x75 }, ++ { CCI_REG8(0x5eb1), 0x75 }, { CCI_REG8(0x5eb2), 0x75 }, ++ { CCI_REG8(0x5eb3), 0x75 }, { CCI_REG8(0x5eb4), 0x75 }, ++ { CCI_REG8(0x5eb5), 0x75 }, { CCI_REG8(0x5eb6), 0x75 }, ++ { CCI_REG8(0x5eb7), 0x75 }, { CCI_REG8(0x5eb8), 0x75 }, ++ { CCI_REG8(0x5eb9), 0x75 }, { CCI_REG8(0x5eba), 0x75 }, ++ { CCI_REG8(0x5ebb), 0x75 }, { CCI_REG8(0x5ebc), 0x75 }, ++ { CCI_REG8(0x5ebd), 0x75 }, { CCI_REG8(0x5ebe), 0x75 }, ++ { CCI_REG8(0x5ebf), 0x75 }, { CCI_REG8(0x5ec0), 0x75 }, ++ { CCI_REG8(0x5ec1), 0x75 }, { CCI_REG8(0x5ec2), 0x75 }, ++ { CCI_REG8(0x5ec3), 0x75 }, { CCI_REG8(0x5ec4), 0x75 }, ++ { CCI_REG8(0x5ec5), 0x75 }, { CCI_REG8(0x5ec6), 0x75 }, ++ { CCI_REG8(0x5ec7), 0x75 }, { CCI_REG8(0x5ec8), 0x75 }, ++ { CCI_REG8(0x5ec9), 0x75 }, { CCI_REG8(0x5eca), 0x75 }, ++ { CCI_REG8(0x5ecb), 0x75 }, { CCI_REG8(0x5ecc), 0x75 }, ++ { CCI_REG8(0x5ecd), 0x75 }, { CCI_REG8(0x5ece), 0x75 }, ++ { CCI_REG8(0x5ecf), 0x75 }, { CCI_REG8(0x5ed0), 0x75 }, ++ { CCI_REG8(0x5ed1), 0x75 }, { CCI_REG8(0x5ed2), 0x75 }, ++ { CCI_REG8(0x5ed3), 0x75 }, { CCI_REG8(0x5ed4), 0x75 }, ++ { CCI_REG8(0x5ed5), 0x75 }, { CCI_REG8(0x5ed6), 0x75 }, ++ { CCI_REG8(0x5ed7), 0x75 }, { CCI_REG8(0x5ed8), 0x75 }, ++ { CCI_REG8(0x5ed9), 0x75 }, { CCI_REG8(0x5eda), 0x75 }, ++ { CCI_REG8(0x5edb), 0x75 }, { CCI_REG8(0x5edc), 0x75 }, ++ { CCI_REG8(0x5edd), 0x75 }, { CCI_REG8(0x5ede), 0x75 }, ++ { CCI_REG8(0x5edf), 0x75 }, { CCI_REG8(0xfff9), 0x08 }, ++ { CCI_REG8(0x1570), 0x00 }, { CCI_REG8(0x15d0), 0x00 }, ++ { CCI_REG8(0x15a0), 0x02 }, { CCI_REG8(0x15a1), 0x00 }, ++ { CCI_REG8(0x15a2), 0x02 }, { CCI_REG8(0x15a3), 0x76 }, ++ { CCI_REG8(0x15a4), 0x03 }, { CCI_REG8(0x15a5), 0x08 }, ++ { CCI_REG8(0x15a6), 0x00 }, { CCI_REG8(0x15a7), 0x60 }, ++ { CCI_REG8(0x15a8), 0x01 }, { CCI_REG8(0x15a9), 0x00 }, ++ { CCI_REG8(0x15aa), 0x02 }, { CCI_REG8(0x15ab), 0x00 }, ++ { CCI_REG8(0x1600), 0x02 }, { CCI_REG8(0x1601), 0x00 }, ++ { CCI_REG8(0x1602), 0x02 }, { CCI_REG8(0x1603), 0x76 }, ++ { CCI_REG8(0x1604), 0x03 }, { CCI_REG8(0x1605), 0x08 }, ++ { CCI_REG8(0x1606), 0x00 }, { CCI_REG8(0x1607), 0x60 }, ++ { CCI_REG8(0x1608), 0x01 }, { CCI_REG8(0x1609), 0x00 }, ++ { CCI_REG8(0x160a), 0x02 }, { CCI_REG8(0x160b), 0x00 }, ++ { CCI_REG8(0x1633), 0x03 }, { CCI_REG8(0x1634), 0x01 }, ++ { CCI_REG8(0x163c), 0x3a }, { CCI_REG8(0x163d), 0x01 }, ++ { CCI_REG8(0x1648), 0x32 }, { CCI_REG8(0x1658), 0x01 }, ++ { CCI_REG8(0x1659), 0x01 }, { CCI_REG8(0x165f), 0x01 }, ++ { CCI_REG8(0x1677), 0x01 }, { CCI_REG8(0x1690), 0x08 }, ++ { CCI_REG8(0x1691), 0x00 }, { CCI_REG8(0x1692), 0x20 }, ++ { CCI_REG8(0x1693), 0x00 }, { CCI_REG8(0x1694), 0x10 }, ++ { CCI_REG8(0x1695), 0x14 }, { CCI_REG8(0x1696), 0x10 }, ++ { CCI_REG8(0x1697), 0x0e }, { CCI_REG8(0x1730), 0x01 }, ++ { CCI_REG8(0x1732), 0x00 }, { CCI_REG8(0x1733), 0x10 }, ++ { CCI_REG8(0x1734), 0x01 }, { CCI_REG8(0x1735), 0x00 }, ++ { CCI_REG8(0x1748), 0x01 }, { CCI_REG8(0xfff9), 0x06 }, ++ { CCI_REG8(0x5000), 0xff }, { CCI_REG8(0x5001), 0x3d }, ++ { CCI_REG8(0x5002), 0xf5 }, { CCI_REG8(0x5004), 0x80 }, ++ { CCI_REG8(0x5006), 0x04 }, { CCI_REG8(0x5061), 0x20 }, ++ { CCI_REG8(0x5063), 0x20 }, { CCI_REG8(0x5064), 0x24 }, ++ { CCI_REG8(0x5065), 0x00 }, { CCI_REG8(0x5066), 0x1b }, ++ { CCI_REG8(0x5067), 0x00 }, { CCI_REG8(0x5068), 0x03 }, ++ { CCI_REG8(0x5069), 0x10 }, { CCI_REG8(0x506a), 0x20 }, ++ { CCI_REG8(0x506b), 0x04 }, { CCI_REG8(0x506c), 0x04 }, ++ { CCI_REG8(0x506d), 0x0c }, { CCI_REG8(0x506e), 0x0c }, ++ { CCI_REG8(0x506f), 0x04 }, { CCI_REG8(0x5070), 0x0c }, ++ { CCI_REG8(0x5071), 0x14 }, { CCI_REG8(0x5072), 0x1c }, ++ { CCI_REG8(0x5073), 0x01 }, { CCI_REG8(0x5074), 0x01 }, ++ { CCI_REG8(0x5075), 0xbe }, { CCI_REG8(0x5083), 0x00 }, ++ { CCI_REG8(0x5114), 0x03 }, { CCI_REG8(0x51b0), 0x00 }, ++ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x02 }, ++ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 }, ++ { CCI_REG8(0x51b8), 0x00 }, { CCI_REG8(0x51b9), 0x70 }, ++ { CCI_REG8(0x51ba), 0x00 }, { CCI_REG8(0x51bb), 0x10 }, ++ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 }, ++ { CCI_REG8(0x51d2), 0xff }, { CCI_REG8(0x51d3), 0x1c }, ++ { CCI_REG8(0x5250), 0x34 }, { CCI_REG8(0x5251), 0x00 }, ++ { CCI_REG8(0x525b), 0x00 }, { CCI_REG8(0x525d), 0x00 }, ++ { CCI_REG8(0x527a), 0x00 }, { CCI_REG8(0x527b), 0x38 }, ++ { CCI_REG8(0x527c), 0x00 }, { CCI_REG8(0x527d), 0x4b }, ++ { CCI_REG8(0x5286), 0x1b }, { CCI_REG8(0x5287), 0x40 }, ++ { CCI_REG8(0x5290), 0x00 }, { CCI_REG8(0x5291), 0x50 }, ++ { CCI_REG8(0x5292), 0x00 }, { CCI_REG8(0x5293), 0x50 }, ++ { CCI_REG8(0x5294), 0x00 }, { CCI_REG8(0x5295), 0x50 }, ++ { CCI_REG8(0x5296), 0x00 }, { CCI_REG8(0x5297), 0x50 }, ++ { CCI_REG8(0x5298), 0x00 }, { CCI_REG8(0x5299), 0x50 }, ++ { CCI_REG8(0x529a), 0x01 }, { CCI_REG8(0x529b), 0x00 }, ++ { CCI_REG8(0x529c), 0x01 }, { CCI_REG8(0x529d), 0x00 }, ++ { CCI_REG8(0x529e), 0x00 }, { CCI_REG8(0x529f), 0x50 }, ++ { CCI_REG8(0x52a0), 0x00 }, { CCI_REG8(0x52a1), 0x50 }, ++ { CCI_REG8(0x52a2), 0x01 }, { CCI_REG8(0x52a3), 0x00 }, ++ { CCI_REG8(0x52a4), 0x01 }, { CCI_REG8(0x52a5), 0x00 }, ++ { CCI_REG8(0x52a6), 0x00 }, { CCI_REG8(0x52a7), 0x50 }, ++ { CCI_REG8(0x52a8), 0x00 }, { CCI_REG8(0x52a9), 0x50 }, ++ { CCI_REG8(0x52aa), 0x00 }, { CCI_REG8(0x52ab), 0x50 }, ++ { CCI_REG8(0x52ac), 0x00 }, { CCI_REG8(0x52ad), 0x50 }, ++ { CCI_REG8(0x52ae), 0x00 }, { CCI_REG8(0x52af), 0x50 }, ++ { CCI_REG8(0x52b0), 0x00 }, { CCI_REG8(0x52b1), 0x50 }, ++ { CCI_REG8(0x52b2), 0x00 }, { CCI_REG8(0x52b3), 0x50 }, ++ { CCI_REG8(0x52b4), 0x00 }, { CCI_REG8(0x52b5), 0x50 }, ++ { CCI_REG8(0x52b6), 0x00 }, { CCI_REG8(0x52b7), 0x50 }, ++ { CCI_REG8(0x52b8), 0x00 }, { CCI_REG8(0x52b9), 0x50 }, ++ { CCI_REG8(0x52ba), 0x01 }, { CCI_REG8(0x52bb), 0x00 }, ++ { CCI_REG8(0x52bc), 0x01 }, { CCI_REG8(0x52bd), 0x00 }, ++ { CCI_REG8(0x52be), 0x00 }, { CCI_REG8(0x52bf), 0x50 }, ++ { CCI_REG8(0x52c0), 0x00 }, { CCI_REG8(0x52c1), 0x50 }, ++ { CCI_REG8(0x52c2), 0x01 }, { CCI_REG8(0x52c3), 0x00 }, ++ { CCI_REG8(0x52c4), 0x01 }, { CCI_REG8(0x52c5), 0x00 }, ++ { CCI_REG8(0x52c6), 0x00 }, { CCI_REG8(0x52c7), 0x50 }, ++ { CCI_REG8(0x52c8), 0x00 }, { CCI_REG8(0x52c9), 0x50 }, ++ { CCI_REG8(0x52ca), 0x00 }, { CCI_REG8(0x52cb), 0x50 }, ++ { CCI_REG8(0x52cc), 0x00 }, { CCI_REG8(0x52cd), 0x50 }, ++ { CCI_REG8(0x52ce), 0x00 }, { CCI_REG8(0x52cf), 0x50 }, ++ { CCI_REG8(0x52f0), 0x04 }, { CCI_REG8(0x52f1), 0x03 }, ++ { CCI_REG8(0x52f2), 0x02 }, { CCI_REG8(0x52f3), 0x01 }, ++ { CCI_REG8(0x52f4), 0x08 }, { CCI_REG8(0x52f5), 0x07 }, ++ { CCI_REG8(0x52f6), 0x06 }, { CCI_REG8(0x52f7), 0x05 }, ++ { CCI_REG8(0x52f8), 0x0c }, { CCI_REG8(0x52f9), 0x0b }, ++ { CCI_REG8(0x52fa), 0x0a }, { CCI_REG8(0x52fb), 0x09 }, ++ { CCI_REG8(0x52fc), 0x10 }, { CCI_REG8(0x52fd), 0x0f }, ++ { CCI_REG8(0x52fe), 0x0e }, { CCI_REG8(0x52ff), 0x0d }, ++ { CCI_REG8(0x5300), 0x14 }, { CCI_REG8(0x5301), 0x13 }, ++ { CCI_REG8(0x5302), 0x12 }, { CCI_REG8(0x5303), 0x11 }, ++ { CCI_REG8(0x5304), 0x18 }, { CCI_REG8(0x5305), 0x17 }, ++ { CCI_REG8(0x5306), 0x16 }, { CCI_REG8(0x5307), 0x15 }, ++ { CCI_REG8(0x5308), 0x1c }, { CCI_REG8(0x5309), 0x1b }, ++ { CCI_REG8(0x530a), 0x1a }, { CCI_REG8(0x530b), 0x19 }, ++ { CCI_REG8(0x530c), 0x20 }, { CCI_REG8(0x530d), 0x1f }, ++ { CCI_REG8(0x530e), 0x1e }, { CCI_REG8(0x530f), 0x1d }, ++ { CCI_REG8(0x5310), 0x03 }, { CCI_REG8(0x5311), 0xe8 }, ++ { CCI_REG8(0x5331), 0x0a }, { CCI_REG8(0x5332), 0x43 }, ++ { CCI_REG8(0x5333), 0x45 }, { CCI_REG8(0x5353), 0x09 }, ++ { CCI_REG8(0x5354), 0x00 }, { CCI_REG8(0x5414), 0x03 }, ++ { CCI_REG8(0x54b0), 0x10 }, { CCI_REG8(0x54b3), 0x0e }, ++ { CCI_REG8(0x54b5), 0x02 }, { CCI_REG8(0x54b6), 0x00 }, ++ { CCI_REG8(0x54b7), 0x00 }, { CCI_REG8(0x54b8), 0x00 }, ++ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54ba), 0x00 }, ++ { CCI_REG8(0x54bb), 0x10 }, { CCI_REG8(0x54bc), 0x00 }, ++ { CCI_REG8(0x54bd), 0x00 }, { CCI_REG8(0x54d2), 0xff }, ++ { CCI_REG8(0x54d3), 0x1c }, { CCI_REG8(0x5510), 0x03 }, ++ { CCI_REG8(0x5511), 0xe8 }, { CCI_REG8(0x5550), 0x6c }, ++ { CCI_REG8(0x5551), 0x00 }, { CCI_REG8(0x557a), 0x00 }, ++ { CCI_REG8(0x557b), 0x38 }, { CCI_REG8(0x557c), 0x00 }, ++ { CCI_REG8(0x557d), 0x4b }, { CCI_REG8(0x5590), 0x00 }, ++ { CCI_REG8(0x5591), 0x50 }, { CCI_REG8(0x5592), 0x00 }, ++ { CCI_REG8(0x5593), 0x50 }, { CCI_REG8(0x5594), 0x00 }, ++ { CCI_REG8(0x5595), 0x50 }, { CCI_REG8(0x5596), 0x00 }, ++ { CCI_REG8(0x5597), 0x50 }, { CCI_REG8(0x5598), 0x00 }, ++ { CCI_REG8(0x5599), 0x50 }, { CCI_REG8(0x559a), 0x01 }, ++ { CCI_REG8(0x559b), 0x00 }, { CCI_REG8(0x559c), 0x01 }, ++ { CCI_REG8(0x559d), 0x00 }, { CCI_REG8(0x559e), 0x00 }, ++ { CCI_REG8(0x559f), 0x50 }, { CCI_REG8(0x55a0), 0x00 }, ++ { CCI_REG8(0x55a1), 0x50 }, { CCI_REG8(0x55a2), 0x01 }, ++ { CCI_REG8(0x55a3), 0x00 }, { CCI_REG8(0x55a4), 0x01 }, ++ { CCI_REG8(0x55a5), 0x00 }, { CCI_REG8(0x55a6), 0x00 }, ++ { CCI_REG8(0x55a7), 0x50 }, { CCI_REG8(0x55a8), 0x00 }, ++ { CCI_REG8(0x55a9), 0x50 }, { CCI_REG8(0x55aa), 0x00 }, ++ { CCI_REG8(0x55ab), 0x50 }, { CCI_REG8(0x55ac), 0x00 }, ++ { CCI_REG8(0x55ad), 0x50 }, { CCI_REG8(0x55ae), 0x00 }, ++ { CCI_REG8(0x55af), 0x50 }, { CCI_REG8(0x55b0), 0x00 }, ++ { CCI_REG8(0x55b1), 0x50 }, { CCI_REG8(0x55b2), 0x00 }, ++ { CCI_REG8(0x55b3), 0x50 }, { CCI_REG8(0x55b4), 0x00 }, ++ { CCI_REG8(0x55b5), 0x50 }, { CCI_REG8(0x55b6), 0x00 }, ++ { CCI_REG8(0x55b7), 0x50 }, { CCI_REG8(0x55b8), 0x00 }, ++ { CCI_REG8(0x55b9), 0x50 }, { CCI_REG8(0x55ba), 0x01 }, ++ { CCI_REG8(0x55bb), 0x00 }, { CCI_REG8(0x55bc), 0x01 }, ++ { CCI_REG8(0x55bd), 0x00 }, { CCI_REG8(0x55be), 0x00 }, ++ { CCI_REG8(0x55bf), 0x50 }, { CCI_REG8(0x55c0), 0x00 }, ++ { CCI_REG8(0x55c1), 0x50 }, { CCI_REG8(0x55c2), 0x01 }, ++ { CCI_REG8(0x55c3), 0x00 }, { CCI_REG8(0x55c4), 0x01 }, ++ { CCI_REG8(0x55c5), 0x00 }, { CCI_REG8(0x55c6), 0x00 }, ++ { CCI_REG8(0x55c7), 0x50 }, { CCI_REG8(0x55c8), 0x00 }, ++ { CCI_REG8(0x55c9), 0x50 }, { CCI_REG8(0x55ca), 0x00 }, ++ { CCI_REG8(0x55cb), 0x50 }, { CCI_REG8(0x55cc), 0x00 }, ++ { CCI_REG8(0x55cd), 0x50 }, { CCI_REG8(0x55ce), 0x00 }, ++ { CCI_REG8(0x55cf), 0x50 }, { CCI_REG8(0x55f0), 0x04 }, ++ { CCI_REG8(0x55f1), 0x03 }, { CCI_REG8(0x55f2), 0x02 }, ++ { CCI_REG8(0x55f3), 0x01 }, { CCI_REG8(0x55f4), 0x08 }, ++ { CCI_REG8(0x55f5), 0x07 }, { CCI_REG8(0x55f6), 0x06 }, ++ { CCI_REG8(0x55f7), 0x05 }, { CCI_REG8(0x55f8), 0x0c }, ++ { CCI_REG8(0x55f9), 0x0b }, { CCI_REG8(0x55fa), 0x0a }, ++ { CCI_REG8(0x55fb), 0x09 }, { CCI_REG8(0x55fc), 0x10 }, ++ { CCI_REG8(0x55fd), 0x0f }, { CCI_REG8(0x55fe), 0x0e }, ++ { CCI_REG8(0x55ff), 0x0d }, { CCI_REG8(0x5600), 0x14 }, ++ { CCI_REG8(0x5601), 0x13 }, { CCI_REG8(0x5602), 0x12 }, ++ { CCI_REG8(0x5603), 0x11 }, { CCI_REG8(0x5604), 0x18 }, ++ { CCI_REG8(0x5605), 0x17 }, { CCI_REG8(0x5606), 0x16 }, ++ { CCI_REG8(0x5607), 0x15 }, { CCI_REG8(0x5608), 0x1c }, ++ { CCI_REG8(0x5609), 0x1b }, { CCI_REG8(0x560a), 0x1a }, ++ { CCI_REG8(0x560b), 0x19 }, { CCI_REG8(0x560c), 0x20 }, ++ { CCI_REG8(0x560d), 0x1f }, { CCI_REG8(0x560e), 0x1e }, ++ { CCI_REG8(0x560f), 0x1d }, { CCI_REG8(0x5631), 0x02 }, ++ { CCI_REG8(0x5632), 0x42 }, { CCI_REG8(0x5633), 0x24 }, ++ { CCI_REG8(0x5653), 0x09 }, { CCI_REG8(0x5654), 0x00 }, ++ { CCI_REG8(0x5714), 0x03 }, { CCI_REG8(0x57b0), 0x10 }, ++ { CCI_REG8(0x57b3), 0x0e }, { CCI_REG8(0x57b5), 0x02 }, ++ { CCI_REG8(0x57b6), 0x00 }, { CCI_REG8(0x57b7), 0x00 }, ++ { CCI_REG8(0x57b8), 0x00 }, { CCI_REG8(0x57b9), 0x70 }, ++ { CCI_REG8(0x57ba), 0x00 }, { CCI_REG8(0x57bb), 0x10 }, ++ { CCI_REG8(0x57bc), 0x00 }, { CCI_REG8(0x57bd), 0x00 }, ++ { CCI_REG8(0x57d2), 0xff }, { CCI_REG8(0x57d3), 0x1c }, ++ { CCI_REG8(0x5810), 0x03 }, { CCI_REG8(0x5811), 0xe8 }, ++ { CCI_REG8(0x5850), 0x6c }, { CCI_REG8(0x5851), 0x00 }, ++ { CCI_REG8(0x587a), 0x00 }, { CCI_REG8(0x587b), 0x38 }, ++ { CCI_REG8(0x587c), 0x00 }, { CCI_REG8(0x587d), 0x4b }, ++ { CCI_REG8(0x5890), 0x00 }, { CCI_REG8(0x5891), 0x50 }, ++ { CCI_REG8(0x5892), 0x00 }, { CCI_REG8(0x5893), 0x50 }, ++ { CCI_REG8(0x5894), 0x00 }, { CCI_REG8(0x5895), 0x50 }, ++ { CCI_REG8(0x5896), 0x00 }, { CCI_REG8(0x5897), 0x50 }, ++ { CCI_REG8(0x5898), 0x00 }, { CCI_REG8(0x5899), 0x50 }, ++ { CCI_REG8(0x589a), 0x01 }, { CCI_REG8(0x589b), 0x00 }, ++ { CCI_REG8(0x589c), 0x01 }, { CCI_REG8(0x589d), 0x00 }, ++ { CCI_REG8(0x589e), 0x00 }, { CCI_REG8(0x589f), 0x50 }, ++ { CCI_REG8(0x58a0), 0x00 }, { CCI_REG8(0x58a1), 0x50 }, ++ { CCI_REG8(0x58a2), 0x01 }, { CCI_REG8(0x58a3), 0x00 }, ++ { CCI_REG8(0x58a4), 0x01 }, { CCI_REG8(0x58a5), 0x00 }, ++ { CCI_REG8(0x58a6), 0x00 }, { CCI_REG8(0x58a7), 0x50 }, ++ { CCI_REG8(0x58a8), 0x00 }, { CCI_REG8(0x58a9), 0x50 }, ++ { CCI_REG8(0x58aa), 0x00 }, { CCI_REG8(0x58ab), 0x50 }, ++ { CCI_REG8(0x58ac), 0x00 }, { CCI_REG8(0x58ad), 0x50 }, ++ { CCI_REG8(0x58ae), 0x00 }, { CCI_REG8(0x58af), 0x50 }, ++ { CCI_REG8(0x58b0), 0x00 }, { CCI_REG8(0x58b1), 0x50 }, ++ { CCI_REG8(0x58b2), 0x00 }, { CCI_REG8(0x58b3), 0x50 }, ++ { CCI_REG8(0x58b4), 0x00 }, { CCI_REG8(0x58b5), 0x50 }, ++ { CCI_REG8(0x58b6), 0x00 }, { CCI_REG8(0x58b7), 0x50 }, ++ { CCI_REG8(0x58b8), 0x00 }, { CCI_REG8(0x58b9), 0x50 }, ++ { CCI_REG8(0x58ba), 0x01 }, { CCI_REG8(0x58bb), 0x00 }, ++ { CCI_REG8(0x58bc), 0x01 }, { CCI_REG8(0x58bd), 0x00 }, ++ { CCI_REG8(0x58be), 0x00 }, { CCI_REG8(0x58bf), 0x50 }, ++ { CCI_REG8(0x58c0), 0x00 }, { CCI_REG8(0x58c1), 0x50 }, ++ { CCI_REG8(0x58c2), 0x01 }, { CCI_REG8(0x58c3), 0x00 }, ++ { CCI_REG8(0x58c4), 0x01 }, { CCI_REG8(0x58c5), 0x00 }, ++ { CCI_REG8(0x58c6), 0x00 }, { CCI_REG8(0x58c7), 0x50 }, ++ { CCI_REG8(0x58c8), 0x00 }, { CCI_REG8(0x58c9), 0x50 }, ++ { CCI_REG8(0x58ca), 0x00 }, { CCI_REG8(0x58cb), 0x50 }, ++ { CCI_REG8(0x58cc), 0x00 }, { CCI_REG8(0x58cd), 0x50 }, ++ { CCI_REG8(0x58ce), 0x00 }, { CCI_REG8(0x58cf), 0x50 }, ++ { CCI_REG8(0x58f0), 0x04 }, { CCI_REG8(0x58f1), 0x03 }, ++ { CCI_REG8(0x58f2), 0x02 }, { CCI_REG8(0x58f3), 0x01 }, ++ { CCI_REG8(0x58f4), 0x08 }, { CCI_REG8(0x58f5), 0x07 }, ++ { CCI_REG8(0x58f6), 0x06 }, { CCI_REG8(0x58f7), 0x05 }, ++ { CCI_REG8(0x58f8), 0x0c }, { CCI_REG8(0x58f9), 0x0b }, ++ { CCI_REG8(0x58fa), 0x0a }, { CCI_REG8(0x58fb), 0x09 }, ++ { CCI_REG8(0x58fc), 0x10 }, { CCI_REG8(0x58fd), 0x0f }, ++ { CCI_REG8(0x58fe), 0x0e }, { CCI_REG8(0x58ff), 0x0d }, ++ { CCI_REG8(0x5900), 0x14 }, { CCI_REG8(0x5901), 0x13 }, ++ { CCI_REG8(0x5902), 0x12 }, { CCI_REG8(0x5903), 0x11 }, ++ { CCI_REG8(0x5904), 0x18 }, { CCI_REG8(0x5905), 0x17 }, ++ { CCI_REG8(0x5906), 0x16 }, { CCI_REG8(0x5907), 0x15 }, ++ { CCI_REG8(0x5908), 0x1c }, { CCI_REG8(0x5909), 0x1b }, ++ { CCI_REG8(0x590a), 0x1a }, { CCI_REG8(0x590b), 0x19 }, ++ { CCI_REG8(0x590c), 0x20 }, { CCI_REG8(0x590d), 0x1f }, ++ { CCI_REG8(0x590e), 0x1e }, { CCI_REG8(0x590f), 0x1d }, ++ { CCI_REG8(0x5931), 0x02 }, { CCI_REG8(0x5932), 0x42 }, ++ { CCI_REG8(0x5933), 0x24 }, { CCI_REG8(0x5953), 0x09 }, ++ { CCI_REG8(0x5954), 0x00 }, { CCI_REG8(0x5989), 0x84 }, ++ { CCI_REG8(0x59c3), 0x04 }, { CCI_REG8(0x59c4), 0x24 }, ++ { CCI_REG8(0x59c5), 0x40 }, { CCI_REG8(0x59c6), 0x1b }, ++ { CCI_REG8(0x59c7), 0x40 }, { CCI_REG8(0x5a02), 0x0f }, ++ { CCI_REG8(0x5f00), 0x29 }, { CCI_REG8(0x5f2d), 0x28 }, ++ { CCI_REG8(0x5f2e), 0x28 }, { CCI_REG8(0x6801), 0x11 }, ++ { CCI_REG8(0x6802), 0x3f }, { CCI_REG8(0x6803), 0xe7 }, ++ { CCI_REG8(0x6825), 0x0f }, { CCI_REG8(0x6826), 0x20 }, ++ { CCI_REG8(0x6827), 0x00 }, { CCI_REG8(0x6829), 0x16 }, ++ { CCI_REG8(0x682b), 0xb3 }, { CCI_REG8(0x682c), 0x01 }, ++ { CCI_REG8(0x6832), 0xff }, { CCI_REG8(0x6833), 0xff }, ++ { CCI_REG8(0x6898), 0x80 }, { CCI_REG8(0x6899), 0x80 }, ++ { CCI_REG8(0x689b), 0x40 }, { CCI_REG8(0x689c), 0x20 }, ++ { CCI_REG8(0x689d), 0x20 }, { CCI_REG8(0x689e), 0x80 }, ++ { CCI_REG8(0x689f), 0x60 }, { CCI_REG8(0x68a0), 0x40 }, ++ { CCI_REG8(0x68a4), 0x40 }, { CCI_REG8(0x68a5), 0x20 }, ++ { CCI_REG8(0x68a6), 0x00 }, { CCI_REG8(0x68b6), 0x80 }, ++ { CCI_REG8(0x68b7), 0x80 }, { CCI_REG8(0x68b8), 0x80 }, ++ { CCI_REG8(0x68bc), 0x80 }, { CCI_REG8(0x68bd), 0x80 }, ++ { CCI_REG8(0x68be), 0x80 }, { CCI_REG8(0x68bf), 0x40 }, ++ { CCI_REG8(0x68c2), 0x80 }, { CCI_REG8(0x68c3), 0x80 }, ++ { CCI_REG8(0x68c4), 0x60 }, { CCI_REG8(0x68c5), 0x30 }, ++ { CCI_REG8(0x6918), 0x80 }, { CCI_REG8(0x6919), 0x80 }, ++ { CCI_REG8(0x691b), 0x40 }, { CCI_REG8(0x691c), 0x20 }, ++ { CCI_REG8(0x691d), 0x20 }, { CCI_REG8(0x691e), 0x80 }, ++ { CCI_REG8(0x691f), 0x60 }, { CCI_REG8(0x6920), 0x40 }, ++ { CCI_REG8(0x6924), 0x40 }, { CCI_REG8(0x6925), 0x20 }, ++ { CCI_REG8(0x6926), 0x00 }, { CCI_REG8(0x6936), 0x40 }, ++ { CCI_REG8(0x6937), 0x40 }, { CCI_REG8(0x6938), 0x20 }, ++ { CCI_REG8(0x6939), 0x20 }, { CCI_REG8(0x693a), 0x10 }, ++ { CCI_REG8(0x693b), 0x10 }, { CCI_REG8(0x693c), 0x20 }, ++ { CCI_REG8(0x693d), 0x20 }, { CCI_REG8(0x693e), 0x10 }, ++ { CCI_REG8(0x693f), 0x10 }, { CCI_REG8(0x6940), 0x00 }, ++ { CCI_REG8(0x6941), 0x00 }, { CCI_REG8(0x6942), 0x08 }, ++ { CCI_REG8(0x6943), 0x08 }, { CCI_REG8(0x6944), 0x00 }, ++ { CCI_REG8(0x69c2), 0x07 }, { CCI_REG8(0x6a20), 0x01 }, ++ { CCI_REG8(0x6a23), 0x10 }, { CCI_REG8(0x6a26), 0x3d }, ++ { CCI_REG8(0x6a27), 0x3e }, { CCI_REG8(0x6a38), 0x02 }, ++ { CCI_REG8(0x6a39), 0x20 }, { CCI_REG8(0x6a3a), 0x02 }, ++ { CCI_REG8(0x6a3b), 0x84 }, { CCI_REG8(0x6a3e), 0x02 }, ++ { CCI_REG8(0x6a3f), 0x20 }, { CCI_REG8(0x6a47), 0x3b }, ++ { CCI_REG8(0x6a63), 0x04 }, { CCI_REG8(0x6a65), 0x00 }, ++ { CCI_REG8(0x6a67), 0x0f }, { CCI_REG8(0x6b22), 0x07 }, ++ { CCI_REG8(0x6b23), 0xc2 }, { CCI_REG8(0x6b2f), 0x00 }, ++ { CCI_REG8(0x6b60), 0x1f }, { CCI_REG8(0x6bd2), 0x5a }, ++ { CCI_REG8(0x6c20), 0x50 }, { CCI_REG8(0x6c60), 0x50 }, ++ { CCI_REG8(0x6c61), 0x06 }, { CCI_REG8(0x7318), 0x04 }, ++ { CCI_REG8(0x7319), 0x01 }, { CCI_REG8(0x731a), 0x04 }, ++ { CCI_REG8(0x731b), 0x01 }, { CCI_REG8(0x731c), 0x00 }, ++ { CCI_REG8(0x731d), 0x00 }, { CCI_REG8(0x731e), 0x04 }, ++ { CCI_REG8(0x731f), 0x01 }, { CCI_REG8(0x7320), 0x04 }, ++ { CCI_REG8(0x7321), 0x00 }, { CCI_REG8(0x7322), 0x04 }, ++ { CCI_REG8(0x7323), 0x00 }, { CCI_REG8(0x7324), 0x04 }, ++ { CCI_REG8(0x7325), 0x00 }, { CCI_REG8(0x7326), 0x04 }, ++ { CCI_REG8(0x7327), 0x00 }, { CCI_REG8(0x7600), 0x00 }, ++ { CCI_REG8(0x7601), 0x00 }, { CCI_REG8(0x7602), 0x10 }, ++ { CCI_REG8(0x7603), 0x00 }, { CCI_REG8(0x7604), 0x00 }, ++ { CCI_REG8(0x7605), 0x00 }, { CCI_REG8(0x7606), 0x10 }, ++ { CCI_REG8(0x7607), 0x00 }, { CCI_REG8(0x7608), 0x00 }, ++ { CCI_REG8(0x7609), 0x00 }, { CCI_REG8(0x760a), 0x10 }, ++ { CCI_REG8(0x760b), 0x00 }, { CCI_REG8(0x760c), 0x00 }, ++ { CCI_REG8(0x760d), 0x00 }, { CCI_REG8(0x760e), 0x10 }, ++ { CCI_REG8(0x760f), 0x00 }, { CCI_REG8(0x7610), 0x00 }, ++ { CCI_REG8(0x7611), 0x00 }, { CCI_REG8(0x7612), 0x10 }, ++ { CCI_REG8(0x7613), 0x00 }, { CCI_REG8(0x7614), 0x00 }, ++ { CCI_REG8(0x7615), 0x00 }, { CCI_REG8(0x7616), 0x10 }, ++ { CCI_REG8(0x7617), 0x00 }, { CCI_REG8(0x7618), 0x00 }, ++ { CCI_REG8(0x7619), 0x00 }, { CCI_REG8(0x761a), 0x10 }, ++ { CCI_REG8(0x761b), 0x00 }, { CCI_REG8(0x761c), 0x00 }, ++ { CCI_REG8(0x761d), 0x00 }, { CCI_REG8(0x761e), 0x10 }, ++ { CCI_REG8(0x761f), 0x00 }, { CCI_REG8(0x7620), 0x00 }, ++ { CCI_REG8(0x7621), 0x00 }, { CCI_REG8(0x7622), 0x10 }, ++ { CCI_REG8(0x7623), 0x00 }, { CCI_REG8(0x7624), 0x00 }, ++ { CCI_REG8(0x7625), 0x00 }, { CCI_REG8(0x7626), 0x10 }, ++ { CCI_REG8(0x7627), 0x00 }, { CCI_REG8(0x7628), 0x00 }, ++ { CCI_REG8(0x7629), 0x00 }, { CCI_REG8(0x762a), 0x10 }, ++ { CCI_REG8(0x762b), 0x00 }, { CCI_REG8(0x762c), 0x00 }, ++ { CCI_REG8(0x762d), 0x00 }, { CCI_REG8(0x762e), 0x10 }, ++ { CCI_REG8(0x762f), 0x00 }, { CCI_REG8(0x7630), 0x00 }, ++ { CCI_REG8(0x7631), 0x00 }, { CCI_REG8(0x7632), 0x10 }, ++ { CCI_REG8(0x7633), 0x00 }, { CCI_REG8(0x7634), 0x00 }, ++ { CCI_REG8(0x7635), 0x00 }, { CCI_REG8(0x7636), 0x10 }, ++ { CCI_REG8(0x7637), 0x00 }, { CCI_REG8(0x7638), 0x00 }, ++ { CCI_REG8(0x7639), 0x00 }, { CCI_REG8(0x763a), 0x10 }, ++ { CCI_REG8(0x763b), 0x00 }, { CCI_REG8(0x763c), 0x00 }, ++ { CCI_REG8(0x763d), 0x00 }, { CCI_REG8(0x763e), 0x10 }, ++ { CCI_REG8(0x763f), 0x00 }, { CCI_REG8(0x7640), 0x00 }, ++ { CCI_REG8(0x7641), 0x00 }, { CCI_REG8(0x7642), 0x10 }, ++ { CCI_REG8(0x7643), 0x00 }, { CCI_REG8(0x7644), 0x00 }, ++ { CCI_REG8(0x7645), 0x00 }, { CCI_REG8(0x7646), 0x10 }, ++ { CCI_REG8(0x7647), 0x00 }, { CCI_REG8(0x7648), 0x00 }, ++ { CCI_REG8(0x7649), 0x00 }, { CCI_REG8(0x764a), 0x10 }, ++ { CCI_REG8(0x764b), 0x00 }, { CCI_REG8(0x764c), 0x00 }, ++ { CCI_REG8(0x764d), 0x00 }, { CCI_REG8(0x764e), 0x10 }, ++ { CCI_REG8(0x764f), 0x00 }, { CCI_REG8(0x7650), 0x00 }, ++ { CCI_REG8(0x7651), 0x00 }, { CCI_REG8(0x7652), 0x10 }, ++ { CCI_REG8(0x7653), 0x00 }, { CCI_REG8(0x7654), 0x00 }, ++ { CCI_REG8(0x7655), 0x00 }, { CCI_REG8(0x7656), 0x10 }, ++ { CCI_REG8(0x7657), 0x00 }, { CCI_REG8(0x7658), 0x00 }, ++ { CCI_REG8(0x7659), 0x00 }, { CCI_REG8(0x765a), 0x10 }, ++ { CCI_REG8(0x765b), 0x00 }, { CCI_REG8(0x765c), 0x00 }, ++ { CCI_REG8(0x765d), 0x00 }, { CCI_REG8(0x765e), 0x10 }, ++ { CCI_REG8(0x765f), 0x00 }, { CCI_REG8(0x7660), 0x00 }, ++ { CCI_REG8(0x7661), 0x00 }, { CCI_REG8(0x7662), 0x10 }, ++ { CCI_REG8(0x7663), 0x00 }, { CCI_REG8(0x7664), 0x00 }, ++ { CCI_REG8(0x7665), 0x00 }, { CCI_REG8(0x7666), 0x10 }, ++ { CCI_REG8(0x7667), 0x00 }, { CCI_REG8(0x7668), 0x00 }, ++ { CCI_REG8(0x7669), 0x00 }, { CCI_REG8(0x766a), 0x10 }, ++ { CCI_REG8(0x766b), 0x00 }, { CCI_REG8(0x766c), 0x00 }, ++ { CCI_REG8(0x766d), 0x00 }, { CCI_REG8(0x766e), 0x10 }, ++ { CCI_REG8(0x766f), 0x00 }, { CCI_REG8(0x7670), 0x00 }, ++ { CCI_REG8(0x7671), 0x00 }, { CCI_REG8(0x7672), 0x10 }, ++ { CCI_REG8(0x7673), 0x00 }, { CCI_REG8(0x7674), 0x00 }, ++ { CCI_REG8(0x7675), 0x00 }, { CCI_REG8(0x7676), 0x10 }, ++ { CCI_REG8(0x7677), 0x00 }, { CCI_REG8(0x7678), 0x00 }, ++ { CCI_REG8(0x7679), 0x00 }, { CCI_REG8(0x767a), 0x10 }, ++ { CCI_REG8(0x767b), 0x00 }, { CCI_REG8(0x767c), 0x00 }, ++ { CCI_REG8(0x767d), 0x00 }, { CCI_REG8(0x767e), 0x10 }, ++ { CCI_REG8(0x767f), 0x00 }, { CCI_REG8(0x7680), 0x00 }, ++ { CCI_REG8(0x7681), 0x00 }, { CCI_REG8(0x7682), 0x10 }, ++ { CCI_REG8(0x7683), 0x00 }, { CCI_REG8(0x7684), 0x00 }, ++ { CCI_REG8(0x7685), 0x00 }, { CCI_REG8(0x7686), 0x10 }, ++ { CCI_REG8(0x7687), 0x00 }, { CCI_REG8(0x7688), 0x00 }, ++ { CCI_REG8(0x7689), 0x00 }, { CCI_REG8(0x768a), 0x10 }, ++ { CCI_REG8(0x768b), 0x00 }, { CCI_REG8(0x768c), 0x00 }, ++ { CCI_REG8(0x768d), 0x00 }, { CCI_REG8(0x768e), 0x10 }, ++ { CCI_REG8(0x768f), 0x00 }, { CCI_REG8(0x7690), 0x00 }, ++ { CCI_REG8(0x7691), 0x00 }, { CCI_REG8(0x7692), 0x10 }, ++ { CCI_REG8(0x7693), 0x00 }, { CCI_REG8(0x7694), 0x00 }, ++ { CCI_REG8(0x7695), 0x00 }, { CCI_REG8(0x7696), 0x10 }, ++ { CCI_REG8(0x7697), 0x00 }, { CCI_REG8(0x7698), 0x00 }, ++ { CCI_REG8(0x7699), 0x00 }, { CCI_REG8(0x769a), 0x10 }, ++ { CCI_REG8(0x769b), 0x00 }, { CCI_REG8(0x769c), 0x00 }, ++ { CCI_REG8(0x769d), 0x00 }, { CCI_REG8(0x769e), 0x10 }, ++ { CCI_REG8(0x769f), 0x00 }, { CCI_REG8(0x76a0), 0x00 }, ++ { CCI_REG8(0x76a1), 0x00 }, { CCI_REG8(0x76a2), 0x10 }, ++ { CCI_REG8(0x76a3), 0x00 }, { CCI_REG8(0x76a4), 0x00 }, ++ { CCI_REG8(0x76a5), 0x00 }, { CCI_REG8(0x76a6), 0x10 }, ++ { CCI_REG8(0x76a7), 0x00 }, { CCI_REG8(0x76a8), 0x00 }, ++ { CCI_REG8(0x76a9), 0x00 }, { CCI_REG8(0x76aa), 0x10 }, ++ { CCI_REG8(0x76ab), 0x00 }, { CCI_REG8(0x76ac), 0x00 }, ++ { CCI_REG8(0x76ad), 0x00 }, { CCI_REG8(0x76ae), 0x10 }, ++ { CCI_REG8(0x76af), 0x00 }, { CCI_REG8(0x76b0), 0x00 }, ++ { CCI_REG8(0x76b1), 0x00 }, { CCI_REG8(0x76b2), 0x10 }, ++ { CCI_REG8(0x76b3), 0x00 }, { CCI_REG8(0x76b4), 0x00 }, ++ { CCI_REG8(0x76b5), 0x00 }, { CCI_REG8(0x76b6), 0x10 }, ++ { CCI_REG8(0x76b7), 0x00 }, { CCI_REG8(0x76b8), 0x00 }, ++ { CCI_REG8(0x76b9), 0x00 }, { CCI_REG8(0x76ba), 0x10 }, ++ { CCI_REG8(0x76bb), 0x00 }, { CCI_REG8(0x76bc), 0x00 }, ++ { CCI_REG8(0x76bd), 0x00 }, { CCI_REG8(0x76be), 0x10 }, ++ { CCI_REG8(0x76bf), 0x00 }, { CCI_REG8(0x76c0), 0x00 }, ++ { CCI_REG8(0x76c1), 0x00 }, { CCI_REG8(0x76c2), 0x10 }, ++ { CCI_REG8(0x76c3), 0x00 }, { CCI_REG8(0x76c4), 0x00 }, ++ { CCI_REG8(0x76c5), 0x00 }, { CCI_REG8(0x76c6), 0x10 }, ++ { CCI_REG8(0x76c7), 0x00 }, { CCI_REG8(0x76c8), 0x00 }, ++ { CCI_REG8(0x76c9), 0x00 }, { CCI_REG8(0x76ca), 0x10 }, ++ { CCI_REG8(0x76cb), 0x00 }, { CCI_REG8(0x76cc), 0x00 }, ++ { CCI_REG8(0x76cd), 0x00 }, { CCI_REG8(0x76ce), 0x10 }, ++ { CCI_REG8(0x76cf), 0x00 }, { CCI_REG8(0x76d0), 0x00 }, ++ { CCI_REG8(0x76d1), 0x00 }, { CCI_REG8(0x76d2), 0x10 }, ++ { CCI_REG8(0x76d3), 0x00 }, { CCI_REG8(0x76d4), 0x00 }, ++ { CCI_REG8(0x76d5), 0x00 }, { CCI_REG8(0x76d6), 0x10 }, ++ { CCI_REG8(0x76d7), 0x00 }, { CCI_REG8(0x76d8), 0x00 }, ++ { CCI_REG8(0x76d9), 0x00 }, { CCI_REG8(0x76da), 0x10 }, ++ { CCI_REG8(0x76db), 0x00 }, { CCI_REG8(0x76dc), 0x00 }, ++ { CCI_REG8(0x76dd), 0x00 }, { CCI_REG8(0x76de), 0x10 }, ++ { CCI_REG8(0x76df), 0x00 }, { CCI_REG8(0x76e0), 0x00 }, ++ { CCI_REG8(0x76e1), 0x00 }, { CCI_REG8(0x76e2), 0x10 }, ++ { CCI_REG8(0x76e3), 0x00 }, { CCI_REG8(0x76e4), 0x00 }, ++ { CCI_REG8(0x76e5), 0x00 }, { CCI_REG8(0x76e6), 0x10 }, ++ { CCI_REG8(0x76e7), 0x00 }, { CCI_REG8(0x76e8), 0x00 }, ++ { CCI_REG8(0x76e9), 0x00 }, { CCI_REG8(0x76ea), 0x10 }, ++ { CCI_REG8(0x76eb), 0x00 }, { CCI_REG8(0x76ec), 0x00 }, ++ { CCI_REG8(0x76ed), 0x00 }, { CCI_REG8(0x76ee), 0x10 }, ++ { CCI_REG8(0x76ef), 0x00 }, { CCI_REG8(0x76f0), 0x00 }, ++ { CCI_REG8(0x76f1), 0x00 }, { CCI_REG8(0x76f2), 0x10 }, ++ { CCI_REG8(0x76f3), 0x00 }, { CCI_REG8(0x76f4), 0x00 }, ++ { CCI_REG8(0x76f5), 0x00 }, { CCI_REG8(0x76f6), 0x10 }, ++ { CCI_REG8(0x76f7), 0x00 }, { CCI_REG8(0x76f8), 0x00 }, ++ { CCI_REG8(0x76f9), 0x00 }, { CCI_REG8(0x76fa), 0x10 }, ++ { CCI_REG8(0x76fb), 0x00 }, { CCI_REG8(0x76fc), 0x00 }, ++ { CCI_REG8(0x76fd), 0x00 }, { CCI_REG8(0x76fe), 0x10 }, ++ { CCI_REG8(0x76ff), 0x00 }, { CCI_REG8(0x7700), 0x00 }, ++ { CCI_REG8(0x7701), 0x00 }, { CCI_REG8(0x7702), 0x10 }, ++ { CCI_REG8(0x7703), 0x00 }, { CCI_REG8(0x7704), 0x00 }, ++ { CCI_REG8(0x7705), 0x00 }, { CCI_REG8(0x7706), 0x10 }, ++ { CCI_REG8(0x7707), 0x00 }, { CCI_REG8(0x7708), 0x00 }, ++ { CCI_REG8(0x7709), 0x00 }, { CCI_REG8(0x770a), 0x10 }, ++ { CCI_REG8(0x770b), 0x00 }, { CCI_REG8(0x770c), 0x00 }, ++ { CCI_REG8(0x770d), 0x00 }, { CCI_REG8(0x770e), 0x10 }, ++ { CCI_REG8(0x770f), 0x00 }, { CCI_REG8(0x7710), 0x00 }, ++ { CCI_REG8(0x7711), 0x00 }, { CCI_REG8(0x7712), 0x10 }, ++ { CCI_REG8(0x7713), 0x00 }, { CCI_REG8(0x7714), 0x00 }, ++ { CCI_REG8(0x7715), 0x00 }, { CCI_REG8(0x7716), 0x10 }, ++ { CCI_REG8(0x7717), 0x00 }, { CCI_REG8(0x7718), 0x00 }, ++ { CCI_REG8(0x7719), 0x00 }, { CCI_REG8(0x771a), 0x10 }, ++ { CCI_REG8(0x771b), 0x00 }, { CCI_REG8(0x771c), 0x00 }, ++ { CCI_REG8(0x771d), 0x00 }, { CCI_REG8(0x771e), 0x10 }, ++ { CCI_REG8(0x771f), 0x00 }, { CCI_REG8(0x7720), 0x00 }, ++ { CCI_REG8(0x7721), 0x00 }, { CCI_REG8(0x7722), 0x10 }, ++ { CCI_REG8(0x7723), 0x00 }, { CCI_REG8(0x7724), 0x00 }, ++ { CCI_REG8(0x7725), 0x00 }, { CCI_REG8(0x7726), 0x10 }, ++ { CCI_REG8(0x7727), 0x00 }, { CCI_REG8(0x7728), 0x00 }, ++ { CCI_REG8(0x7729), 0x00 }, { CCI_REG8(0x772a), 0x10 }, ++ { CCI_REG8(0x772b), 0x00 }, { CCI_REG8(0x772c), 0x00 }, ++ { CCI_REG8(0x772d), 0x00 }, { CCI_REG8(0x772e), 0x10 }, ++ { CCI_REG8(0x772f), 0x00 }, { CCI_REG8(0x7730), 0x00 }, ++ { CCI_REG8(0x7731), 0x00 }, { CCI_REG8(0x7732), 0x10 }, ++ { CCI_REG8(0x7733), 0x00 }, { CCI_REG8(0x7734), 0x00 }, ++ { CCI_REG8(0x7735), 0x00 }, { CCI_REG8(0x7736), 0x10 }, ++ { CCI_REG8(0x7737), 0x00 }, { CCI_REG8(0x7738), 0x00 }, ++ { CCI_REG8(0x7739), 0x00 }, { CCI_REG8(0x773a), 0x10 }, ++ { CCI_REG8(0x773b), 0x00 }, { CCI_REG8(0x773c), 0x00 }, ++ { CCI_REG8(0x773d), 0x00 }, { CCI_REG8(0x773e), 0x10 }, ++ { CCI_REG8(0x773f), 0x00 }, { CCI_REG8(0x7740), 0x00 }, ++ { CCI_REG8(0x7741), 0x00 }, { CCI_REG8(0x7742), 0x10 }, ++ { CCI_REG8(0x7743), 0x00 }, { CCI_REG8(0x3421), 0x02 }, ++ { CCI_REG8(0x37d0), 0x00 }, { CCI_REG8(0x3632), 0x99 }, ++ { CCI_REG8(0xc518), 0x1f }, { CCI_REG8(0xc519), 0x1f }, ++ { CCI_REG8(0xc51a), 0x1f }, { CCI_REG8(0xc51b), 0x1f }, ++ { CCI_REG8(0xc51c), 0x1f }, { CCI_REG8(0xc51d), 0x1f }, ++ { CCI_REG8(0xc51e), 0x1f }, { CCI_REG8(0xc51f), 0x1f }, ++ { CCI_REG8(0xc520), 0x1f }, { CCI_REG8(0xc521), 0x1f }, ++ { CCI_REG8(0x3616), 0xa0 }, { CCI_REG8(0x3615), 0xc5 }, ++ { CCI_REG8(0xc4c1), 0x02 }, { CCI_REG8(0xc4c2), 0x02 }, ++ { CCI_REG8(0xc4c3), 0x03 }, { CCI_REG8(0xc4c4), 0x03 }, ++ { CCI_REG8(0xc4f6), 0x0a }, { CCI_REG8(0xc4f7), 0x0a }, ++ { CCI_REG8(0xc4f8), 0x0a }, { CCI_REG8(0xc4f9), 0x0a }, ++ { CCI_REG8(0xc4fa), 0x0a }, { CCI_REG8(0xc4c6), 0x0a }, ++ { CCI_REG8(0xc4c7), 0x0a }, { CCI_REG8(0xc4c8), 0x0a }, ++ { CCI_REG8(0xc4c9), 0x0a }, { CCI_REG8(0xc4ca), 0x14 }, ++ { CCI_REG8(0xc4cb), 0x14 }, { CCI_REG8(0xc4cc), 0x14 }, ++ { CCI_REG8(0xc4cd), 0x14 }, { CCI_REG8(0x3b92), 0x05 }, ++ { CCI_REG8(0x3b93), 0x05 }, { CCI_REG8(0x3b94), 0x05 }, ++ { CCI_REG8(0x3b95), 0x05 }, { CCI_REG8(0x3623), 0x10 }, ++ { CCI_REG8(0xc522), 0x18 }, { CCI_REG8(0xc523), 0x12 }, ++ { CCI_REG8(0xc524), 0x0e }, { CCI_REG8(0xc525), 0x0b }, ++ { CCI_REG8(0xc526), 0x18 }, { CCI_REG8(0xc527), 0x12 }, ++ { CCI_REG8(0xc528), 0x0c }, { CCI_REG8(0xc529), 0x08 }, ++ { CCI_REG8(0xc52a), 0x18 }, { CCI_REG8(0xc52b), 0x12 }, ++ { CCI_REG8(0xc52c), 0x0e }, { CCI_REG8(0xc52d), 0x0b }, ++ { CCI_REG8(0xc52e), 0x18 }, { CCI_REG8(0xc52f), 0x12 }, ++ { CCI_REG8(0xc530), 0x0e }, { CCI_REG8(0xc531), 0x0b }, ++ { CCI_REG8(0xc532), 0x18 }, { CCI_REG8(0xc533), 0x12 }, ++ { CCI_REG8(0xc534), 0x0e }, { CCI_REG8(0xc535), 0x0b }, ++ { CCI_REG8(0xc536), 0x18 }, { CCI_REG8(0xc537), 0x12 }, ++ { CCI_REG8(0xc538), 0x0e }, { CCI_REG8(0xc539), 0x0b }, ++ { CCI_REG8(0xc53a), 0x18 }, { CCI_REG8(0xc53b), 0x12 }, ++ { CCI_REG8(0xc53c), 0x0c }, { CCI_REG8(0xc53d), 0x08 }, ++ { CCI_REG8(0xc53e), 0x18 }, { CCI_REG8(0xc53f), 0x12 }, ++ { CCI_REG8(0xc540), 0x0e }, { CCI_REG8(0xc541), 0x0b }, ++ { CCI_REG8(0xc542), 0x18 }, { CCI_REG8(0xc543), 0x12 }, ++ { CCI_REG8(0xc544), 0x0e }, { CCI_REG8(0xc545), 0x0b }, ++ { CCI_REG8(0xc546), 0x18 }, { CCI_REG8(0xc547), 0x12 }, ++ { CCI_REG8(0xc548), 0x0e }, { CCI_REG8(0xc549), 0x0b }, ++ { CCI_REG8(0x3701), 0x18 }, { CCI_REG8(0x3702), 0x38 }, ++ { CCI_REG8(0x3703), 0x72 }, { CCI_REG8(0x3708), 0x26 }, ++ { CCI_REG8(0x3709), 0xe6 }, { CCI_REG8(0x3a1d), 0x18 }, ++ { CCI_REG8(0x3a1e), 0x18 }, { CCI_REG8(0x3a21), 0x18 }, ++ { CCI_REG8(0x3a22), 0x18 }, { CCI_REG8(0x39fb), 0x18 }, ++ { CCI_REG8(0x39fc), 0x18 }, { CCI_REG8(0x39fd), 0x18 }, ++ { CCI_REG8(0x39fe), 0x18 }, { CCI_REG8(0xc44a), 0x08 }, ++ { CCI_REG8(0xc44c), 0x08 }, { CCI_REG8(0xc5e8), 0x0a }, ++ { CCI_REG8(0xc5ea), 0x0a }, { CCI_REG8(0x391d), 0x54 }, ++ { CCI_REG8(0x391e), 0xca }, { CCI_REG8(0x3991), 0x0c }, ++ { CCI_REG8(0x399d), 0x0c }, { CCI_REG8(0x3744), 0x24 }, ++ { CCI_REG8(0x374b), 0x0c }, { CCI_REG8(0x3be7), 0x1e }, ++ { CCI_REG8(0x3be8), 0x26 }, { CCI_REG8(0x3a50), 0x14 }, ++ { CCI_REG8(0x3a54), 0x14 }, { CCI_REG8(0x3add), 0x1f }, ++ { CCI_REG8(0x3adf), 0x24 }, { CCI_REG8(0x3aef), 0x1f }, ++ { CCI_REG8(0x3af0), 0x24 }, { CCI_REG8(0xc57f), 0x30 }, ++ { CCI_REG8(0xc580), 0x30 }, { CCI_REG8(0xc581), 0x30 }, ++ { CCI_REG8(0xc582), 0x30 }, { CCI_REG8(0xc583), 0x30 }, ++ { CCI_REG8(0xc584), 0x30 }, { CCI_REG8(0xc585), 0x30 }, ++ { CCI_REG8(0xc586), 0x30 }, { CCI_REG8(0xc587), 0x30 }, ++ { CCI_REG8(0xc588), 0x30 }, { CCI_REG8(0xc589), 0x30 }, ++ { CCI_REG8(0xc58a), 0x30 }, { CCI_REG8(0xc58b), 0x30 }, ++ { CCI_REG8(0xc58c), 0x30 }, { CCI_REG8(0xc58d), 0x30 }, ++ { CCI_REG8(0xc58e), 0x30 }, { CCI_REG8(0xc58f), 0x30 }, ++ { CCI_REG8(0xc590), 0x30 }, { CCI_REG8(0xc591), 0x30 }, ++ { CCI_REG8(0xc592), 0x30 }, { CCI_REG8(0xc598), 0x30 }, ++ { CCI_REG8(0xc599), 0x30 }, { CCI_REG8(0xc59a), 0x30 }, ++ { CCI_REG8(0xc59b), 0x30 }, { CCI_REG8(0xc59c), 0x30 }, ++ { CCI_REG8(0xc59d), 0x30 }, { CCI_REG8(0xc59e), 0x30 }, ++ { CCI_REG8(0xc59f), 0x30 }, { CCI_REG8(0xc5a0), 0x30 }, ++ { CCI_REG8(0xc5a1), 0x30 }, { CCI_REG8(0xc5a2), 0x30 }, ++ { CCI_REG8(0xc5a3), 0x30 }, { CCI_REG8(0xc5a4), 0x30 }, ++ { CCI_REG8(0xc5a5), 0x30 }, { CCI_REG8(0xc5a6), 0x30 }, ++ { CCI_REG8(0xc5a7), 0x30 }, { CCI_REG8(0xc5a8), 0x30 }, ++ { CCI_REG8(0xc5a9), 0x30 }, { CCI_REG8(0xc5aa), 0x30 }, ++ { CCI_REG8(0xc5ab), 0x30 }, { CCI_REG8(0xc5b1), 0x38 }, ++ { CCI_REG8(0xc5b2), 0x38 }, { CCI_REG8(0xc5b3), 0x38 }, ++ { CCI_REG8(0xc5b4), 0x38 }, { CCI_REG8(0xc5b5), 0x38 }, ++ { CCI_REG8(0xc5b6), 0x38 }, { CCI_REG8(0xc5b7), 0x38 }, ++ { CCI_REG8(0xc5b8), 0x38 }, { CCI_REG8(0xc5b9), 0x38 }, ++ { CCI_REG8(0xc5ba), 0x38 }, { CCI_REG8(0xc5bb), 0x38 }, ++ { CCI_REG8(0xc5bc), 0x38 }, { CCI_REG8(0xc5bd), 0x38 }, ++ { CCI_REG8(0xc5be), 0x38 }, { CCI_REG8(0xc5bf), 0x38 }, ++ { CCI_REG8(0xc5c0), 0x38 }, { CCI_REG8(0xc5c1), 0x38 }, ++ { CCI_REG8(0xc5c2), 0x38 }, { CCI_REG8(0xc5c3), 0x38 }, ++ { CCI_REG8(0xc5c4), 0x38 }, { CCI_REG8(0xc5ca), 0x38 }, ++ { CCI_REG8(0xc5cb), 0x38 }, { CCI_REG8(0xc5cc), 0x38 }, ++ { CCI_REG8(0xc5cd), 0x38 }, { CCI_REG8(0xc5ce), 0x38 }, ++ { CCI_REG8(0xc5cf), 0x38 }, { CCI_REG8(0xc5d0), 0x38 }, ++ { CCI_REG8(0xc5d1), 0x38 }, { CCI_REG8(0xc5d2), 0x38 }, ++ { CCI_REG8(0xc5d3), 0x38 }, { CCI_REG8(0xc5d4), 0x38 }, ++ { CCI_REG8(0xc5d5), 0x38 }, { CCI_REG8(0xc5d6), 0x38 }, ++ { CCI_REG8(0xc5d7), 0x38 }, { CCI_REG8(0xc5d8), 0x38 }, ++ { CCI_REG8(0xc5d9), 0x38 }, { CCI_REG8(0xc5da), 0x38 }, ++ { CCI_REG8(0xc5db), 0x38 }, { CCI_REG8(0xc5dc), 0x38 }, ++ { CCI_REG8(0xc5dd), 0x38 }, { CCI_REG8(0x3a60), 0x68 }, ++ { CCI_REG8(0x3a6f), 0x68 }, { CCI_REG8(0x3a5e), 0xdc }, ++ { CCI_REG8(0x3a6d), 0xdc }, { CCI_REG8(0x3aed), 0x6e }, ++ { CCI_REG8(0x3af1), 0x73 }, { CCI_REG8(0x3992), 0x02 }, ++ { CCI_REG8(0x399e), 0x02 }, { CCI_REG8(0x371d), 0x17 }, ++ { CCI_REG8(0x371f), 0x08 }, { CCI_REG8(0x3721), 0xc9 }, ++ { CCI_REG8(0x401e), 0x00 }, { CCI_REG8(0x401f), 0xf8 }, ++ { CCI_REG8(0x3642), 0x00 }, { CCI_REG8(0x3641), 0x7f }, ++ { CCI_REG8(0x3ac5), 0x0c }, { CCI_REG8(0x3ac6), 0x09 }, ++ { CCI_REG8(0x3ac7), 0x06 }, { CCI_REG8(0x3ac8), 0x02 }, ++ { CCI_REG8(0x3ac9), 0x0c }, { CCI_REG8(0x3aca), 0x09 }, ++ { CCI_REG8(0x3acb), 0x06 }, { CCI_REG8(0x3acc), 0x02 }, ++ { CCI_REG8(0x3acd), 0x0c }, { CCI_REG8(0x3ace), 0x09 }, ++ { CCI_REG8(0x3acf), 0x07 }, { CCI_REG8(0x3ad0), 0x04 }, ++ { CCI_REG8(0x3ad1), 0x0c }, { CCI_REG8(0x3ad2), 0x09 }, ++ { CCI_REG8(0x3ad3), 0x07 }, { CCI_REG8(0x3ad4), 0x04 }, ++ { CCI_REG8(0xc483), 0x0c }, { CCI_REG8(0xc484), 0x0c }, ++ { CCI_REG8(0xc485), 0x0c }, { CCI_REG8(0xc486), 0x0c }, ++ { CCI_REG8(0x3a2f), 0x0c }, { CCI_REG8(0x3a30), 0x09 }, ++ { CCI_REG8(0x3a31), 0x06 }, { CCI_REG8(0x3a32), 0x02 }, ++ { CCI_REG8(0x3a34), 0x0c }, { CCI_REG8(0x3a35), 0x09 }, ++ { CCI_REG8(0x3a36), 0x07 }, { CCI_REG8(0x3a37), 0x04 }, ++ { CCI_REG8(0x3a43), 0x0c }, { CCI_REG8(0x3a44), 0x09 }, ++ { CCI_REG8(0x3a45), 0x06 }, { CCI_REG8(0x3a46), 0x02 }, ++ { CCI_REG8(0x3a48), 0x0c }, { CCI_REG8(0x3a49), 0x09 }, ++ { CCI_REG8(0x3a4a), 0x07 }, { CCI_REG8(0x3a4b), 0x04 }, ++ { CCI_REG8(0xc487), 0x0c }, { CCI_REG8(0xc488), 0x0c }, ++ { CCI_REG8(0xc489), 0x0c }, { CCI_REG8(0xc48a), 0x0c }, ++ { CCI_REG8(0x3645), 0xbd }, { CCI_REG8(0x373f), 0x00 }, ++ { CCI_REG8(0x374f), 0x10 }, { CCI_REG8(0x3743), 0xc6 }, ++ { CCI_REG8(0x3717), 0x82 }, { CCI_REG8(0x3732), 0x07 }, ++ { CCI_REG8(0x3731), 0x16 }, { CCI_REG8(0x3730), 0x16 }, ++ { CCI_REG8(0x3828), 0x07 }, { CCI_REG8(0x3714), 0x68 }, ++ { CCI_REG8(0x371d), 0x02 }, { CCI_REG8(0x371f), 0x02 }, ++ { CCI_REG8(0x37e0), 0x00 }, { CCI_REG8(0x37e1), 0x03 }, ++ { CCI_REG8(0x37e2), 0x07 }, { CCI_REG8(0x3734), 0x3e }, ++ { CCI_REG8(0x3736), 0x02 }, { CCI_REG8(0x37e4), 0x36 }, ++ { CCI_REG8(0x37e9), 0x1c }, { CCI_REG8(0x37ea), 0x01 }, ++ { CCI_REG8(0x37eb), 0x0a }, { CCI_REG8(0x37ec), 0x1c }, ++ { CCI_REG8(0x37ed), 0x01 }, { CCI_REG8(0x37ee), 0x36 }, ++ { CCI_REG8(0x373b), 0x1c }, { CCI_REG8(0x373c), 0x02 }, ++ { CCI_REG8(0x37bb), 0x1c }, { CCI_REG8(0x37bc), 0x02 }, ++ { CCI_REG8(0x37b8), 0x0c }, { CCI_REG8(0x371c), 0x01 }, ++ { CCI_REG8(0x371e), 0x11 }, { CCI_REG8(0x371d), 0x01 }, ++ { CCI_REG8(0x371f), 0x01 }, { CCI_REG8(0x3721), 0x01 }, ++ { CCI_REG8(0x3725), 0x12 }, { CCI_REG8(0x37e3), 0x06 }, ++ { CCI_REG8(0x37dd), 0x86 }, { CCI_REG8(0x37db), 0x0a }, ++ { CCI_REG8(0x37dc), 0x14 }, { CCI_REG8(0x3727), 0x20 }, ++ { CCI_REG8(0x37b2), 0x80 }, { CCI_REG8(0x37da), 0x04 }, ++ { CCI_REG8(0x37df), 0x01 }, { CCI_REG8(0x3731), 0x11 }, ++ { CCI_REG8(0x37dd), 0x86 }, { CCI_REG8(0x37df), 0x01 }, ++ { CCI_REG8(0x37da), 0x03 }, { CCI_REG8(0x37b2), 0x80 }, ++ { CCI_REG8(0x3727), 0x20 }, { CCI_REG8(0x4883), 0x26 }, ++ { CCI_REG8(0x488b), 0x88 }, { CCI_REG8(0x3d85), 0x1f }, ++ { CCI_REG8(0x3d81), 0x01 }, { CCI_REG8(0x3d84), 0x40 }, ++ { CCI_REG8(0x3d88), 0x00 }, { CCI_REG8(0x3d89), 0x00 }, ++ { CCI_REG8(0x3d8a), 0x0b }, { CCI_REG8(0x3d8b), 0xff }, ++ { CCI_REG8(0x4d00), 0x05 }, { CCI_REG8(0x4d01), 0xc4 }, ++ { CCI_REG8(0x4d02), 0xa3 }, { CCI_REG8(0x4d03), 0x8c }, ++ { CCI_REG8(0x4d04), 0xfb }, { CCI_REG8(0x4d05), 0xed }, ++ { CCI_REG8(0x4010), 0x28 }, { CCI_REG8(0x4030), 0x00 }, ++ { CCI_REG8(0x4031), 0x00 }, { CCI_REG8(0x4032), 0x00 }, ++ { CCI_REG8(0x4033), 0x00 }, { CCI_REG8(0x4034), 0x00 }, ++ { CCI_REG8(0x4035), 0x00 }, { CCI_REG8(0x4036), 0x00 }, ++ { CCI_REG8(0x4037), 0x00 }, { CCI_REG8(0x4040), 0x00 }, ++ { CCI_REG8(0x4041), 0x00 }, { CCI_REG8(0x4042), 0x00 }, ++ { CCI_REG8(0x4043), 0x00 }, { CCI_REG8(0x4044), 0x00 }, ++ { CCI_REG8(0x4045), 0x00 }, { CCI_REG8(0x4046), 0x00 }, ++ { CCI_REG8(0x4047), 0x00 }, { CCI_REG8(0x3400), 0x00 }, ++ { CCI_REG8(0x3421), 0x23 }, { CCI_REG8(0x3422), 0xfc }, ++ { CCI_REG8(0x3423), 0x07 }, { CCI_REG8(0x3424), 0x01 }, ++ { CCI_REG8(0x3425), 0x04 }, { CCI_REG8(0x3426), 0x50 }, ++ { CCI_REG8(0x3427), 0x55 }, { CCI_REG8(0x3428), 0x15 }, ++ { CCI_REG8(0x3429), 0x00 }, { CCI_REG8(0x3025), 0x03 }, ++ { CCI_REG8(0x3053), 0x00 }, { CCI_REG8(0x3054), 0x00 }, ++ { CCI_REG8(0x3055), 0x00 }, { CCI_REG8(0x3056), 0x00 }, ++ { CCI_REG8(0x3057), 0x00 }, { CCI_REG8(0x3058), 0x00 }, ++ { CCI_REG8(0x305c), 0x00 }, { CCI_REG8(0x340c), 0x1f }, ++ { CCI_REG8(0x340d), 0x00 }, { CCI_REG8(0x3501), 0x01 }, ++ { CCI_REG8(0x3542), 0x48 }, { CCI_REG8(0x3582), 0x24 }, ++ { CCI_REG8(0x3015), 0xf1 }, { CCI_REG8(0x3018), 0xf2 }, ++ { CCI_REG8(0x301c), 0xf2 }, { CCI_REG8(0x301d), 0xf6 }, ++ { CCI_REG8(0x301e), 0xf1 }, { CCI_REG8(0x0100), 0x01 }, ++ { CCI_REG8(0xfff9), 0x08 }, { CCI_REG8(0x3900), 0xcd }, ++ { CCI_REG8(0x3901), 0xcd }, { CCI_REG8(0x3902), 0xcd }, ++ { CCI_REG8(0x3903), 0xcd }, { CCI_REG8(0x3904), 0xcd }, ++ { CCI_REG8(0x3905), 0xcd }, { CCI_REG8(0x3906), 0xcd }, ++ { CCI_REG8(0x3907), 0xcd }, { CCI_REG8(0x3908), 0xcd }, ++ { CCI_REG8(0x3909), 0xcd }, { CCI_REG8(0x390a), 0xcd }, ++ { CCI_REG8(0x390b), 0xcd }, { CCI_REG8(0x390c), 0xcd }, ++ { CCI_REG8(0x390d), 0xcd }, { CCI_REG8(0x390e), 0xcd }, ++ { CCI_REG8(0x390f), 0xcd }, { CCI_REG8(0x3910), 0xcd }, ++ { CCI_REG8(0x3911), 0xcd }, { CCI_REG8(0x3912), 0xcd }, ++ { CCI_REG8(0x3913), 0xcd }, { CCI_REG8(0x3914), 0xcd }, ++ { CCI_REG8(0x3915), 0xcd }, { CCI_REG8(0x3916), 0xcd }, ++ { CCI_REG8(0x3917), 0xcd }, { CCI_REG8(0x3918), 0xcd }, ++ { CCI_REG8(0x3919), 0xcd }, { CCI_REG8(0x391a), 0xcd }, ++ { CCI_REG8(0x391b), 0xcd }, { CCI_REG8(0x391c), 0xcd }, ++ { CCI_REG8(0x391d), 0xcd }, { CCI_REG8(0x391e), 0xcd }, ++ { CCI_REG8(0x391f), 0xcd }, { CCI_REG8(0x3920), 0xcd }, ++ { CCI_REG8(0x3921), 0xcd }, { CCI_REG8(0x3922), 0xcd }, ++ { CCI_REG8(0x3923), 0xcd }, { CCI_REG8(0x3924), 0xcd }, ++ { CCI_REG8(0x3925), 0xcd }, { CCI_REG8(0x3926), 0xcd }, ++ { CCI_REG8(0x3927), 0xcd }, { CCI_REG8(0x3928), 0xcd }, ++ { CCI_REG8(0x3929), 0xcd }, { CCI_REG8(0x392a), 0xcd }, ++ { CCI_REG8(0x392b), 0xcd }, { CCI_REG8(0x392c), 0xcd }, ++ { CCI_REG8(0x392d), 0xcd }, { CCI_REG8(0x392e), 0xcd }, ++ { CCI_REG8(0x392f), 0xcd }, { CCI_REG8(0x3930), 0xcd }, ++ { CCI_REG8(0x3931), 0xcd }, { CCI_REG8(0x3932), 0xcd }, ++ { CCI_REG8(0x3933), 0xcd }, { CCI_REG8(0x3934), 0xcd }, ++ { CCI_REG8(0x3935), 0xcd }, { CCI_REG8(0x3936), 0xcd }, ++ { CCI_REG8(0x3937), 0xcd }, { CCI_REG8(0x3938), 0xcd }, ++ { CCI_REG8(0x3939), 0xcd }, { CCI_REG8(0x393a), 0xcd }, ++ { CCI_REG8(0x393b), 0xcd }, { CCI_REG8(0x393c), 0xcd }, ++ { CCI_REG8(0x393d), 0xcd }, { CCI_REG8(0x393e), 0xcd }, ++ { CCI_REG8(0x393f), 0xcd }, { CCI_REG8(0x3940), 0xcd }, ++ { CCI_REG8(0x3941), 0xcd }, { CCI_REG8(0x3942), 0xcd }, ++ { CCI_REG8(0x3943), 0xcd }, { CCI_REG8(0x3944), 0xcd }, ++ { CCI_REG8(0x3945), 0xcd }, { CCI_REG8(0x3946), 0xcd }, ++ { CCI_REG8(0x3947), 0xcd }, { CCI_REG8(0x3948), 0xcd }, ++ { CCI_REG8(0x3949), 0xcd }, { CCI_REG8(0x394a), 0xcd }, ++ { CCI_REG8(0x394b), 0xcd }, { CCI_REG8(0x394c), 0xcd }, ++ { CCI_REG8(0x394d), 0xcd }, { CCI_REG8(0x394e), 0xcd }, ++ { CCI_REG8(0x394f), 0xcd }, { CCI_REG8(0x3950), 0xcd }, ++ { CCI_REG8(0x3951), 0xcd }, { CCI_REG8(0x3952), 0xcd }, ++ { CCI_REG8(0x3953), 0xcd }, { CCI_REG8(0x3954), 0xcd }, ++ { CCI_REG8(0x3955), 0xcd }, { CCI_REG8(0x3956), 0xcd }, ++ { CCI_REG8(0x3957), 0xcd }, { CCI_REG8(0x3958), 0xcd }, ++ { CCI_REG8(0x3959), 0xcd }, { CCI_REG8(0x395a), 0xcd }, ++ { CCI_REG8(0x395b), 0xcd }, { CCI_REG8(0x395c), 0xcd }, ++ { CCI_REG8(0x395d), 0xcd }, { CCI_REG8(0x395e), 0xcd }, ++ { CCI_REG8(0x395f), 0xcd }, { CCI_REG8(0x3960), 0xcd }, ++ { CCI_REG8(0x3961), 0xcd }, { CCI_REG8(0x3962), 0xcd }, ++ { CCI_REG8(0x3963), 0xcd }, { CCI_REG8(0x3964), 0xcd }, ++ { CCI_REG8(0x3965), 0xcd }, { CCI_REG8(0x3966), 0xcd }, ++ { CCI_REG8(0x3967), 0xcd }, { CCI_REG8(0x3968), 0xcd }, ++ { CCI_REG8(0x3969), 0xcd }, { CCI_REG8(0x396a), 0xcd }, ++ { CCI_REG8(0x396b), 0xcd }, { CCI_REG8(0x396c), 0xcd }, ++ { CCI_REG8(0x396d), 0xcd }, { CCI_REG8(0x396e), 0xcd }, ++ { CCI_REG8(0x396f), 0xcd }, { CCI_REG8(0x3970), 0xcd }, ++ { CCI_REG8(0x3971), 0xcd }, { CCI_REG8(0x3972), 0xcd }, ++ { CCI_REG8(0x3973), 0xcd }, { CCI_REG8(0x3974), 0xcd }, ++ { CCI_REG8(0x3975), 0xcd }, { CCI_REG8(0x3976), 0xcd }, ++ { CCI_REG8(0x3977), 0xcd }, { CCI_REG8(0x3978), 0xcd }, ++ { CCI_REG8(0x3979), 0xcd }, { CCI_REG8(0x397a), 0xcd }, ++ { CCI_REG8(0x397b), 0xcd }, { CCI_REG8(0x397c), 0xcd }, ++ { CCI_REG8(0x397d), 0xcd }, { CCI_REG8(0x397e), 0xcd }, ++ { CCI_REG8(0x397f), 0xcd }, { CCI_REG8(0x3980), 0xcd }, ++ { CCI_REG8(0x3981), 0xcd }, { CCI_REG8(0x3982), 0xcd }, ++ { CCI_REG8(0x3983), 0xcd }, { CCI_REG8(0x3984), 0xcd }, ++ { CCI_REG8(0x3985), 0xcd }, { CCI_REG8(0x3986), 0xcd }, ++ { CCI_REG8(0x3987), 0xcd }, { CCI_REG8(0x3988), 0xcd }, ++ { CCI_REG8(0x3989), 0xcd }, { CCI_REG8(0x398a), 0xcd }, ++ { CCI_REG8(0x398b), 0xcd }, { CCI_REG8(0x398c), 0xcd }, ++ { CCI_REG8(0x398d), 0xcd }, { CCI_REG8(0x398e), 0xcd }, ++ { CCI_REG8(0x398f), 0xcd }, { CCI_REG8(0x3990), 0xcd }, ++ { CCI_REG8(0x3991), 0xcd }, { CCI_REG8(0x3992), 0xcd }, ++ { CCI_REG8(0x3993), 0xcd }, { CCI_REG8(0x3994), 0xcd }, ++ { CCI_REG8(0x3995), 0xcd }, { CCI_REG8(0x3996), 0xcd }, ++ { CCI_REG8(0x3997), 0xcd }, { CCI_REG8(0x3998), 0xcd }, ++ { CCI_REG8(0x3999), 0xcd }, { CCI_REG8(0x399a), 0xcd }, ++ { CCI_REG8(0x399b), 0xcd }, { CCI_REG8(0x399c), 0xcd }, ++ { CCI_REG8(0x399d), 0xcd }, { CCI_REG8(0x399e), 0xcd }, ++ { CCI_REG8(0x399f), 0xcd }, { CCI_REG8(0x39a0), 0xcd }, ++ { CCI_REG8(0x39a1), 0xcd }, { CCI_REG8(0x39a2), 0xcd }, ++ { CCI_REG8(0x39a3), 0xcd }, { CCI_REG8(0x39a4), 0xcd }, ++ { CCI_REG8(0x39a5), 0xcd }, { CCI_REG8(0x39a6), 0xcd }, ++ { CCI_REG8(0x39a7), 0xcd }, { CCI_REG8(0x39a8), 0xcd }, ++ { CCI_REG8(0x39a9), 0xcd }, { CCI_REG8(0x39aa), 0xcd }, ++ { CCI_REG8(0x39ab), 0xcd }, { CCI_REG8(0x39ac), 0xcd }, ++ { CCI_REG8(0x39ad), 0xcd }, { CCI_REG8(0x39ae), 0xcd }, ++ { CCI_REG8(0x39af), 0xcd }, { CCI_REG8(0x39b0), 0xcd }, ++ { CCI_REG8(0x39b1), 0xcd }, { CCI_REG8(0x39b2), 0xcd }, ++ { CCI_REG8(0x39b3), 0xcd }, { CCI_REG8(0x39b4), 0xcd }, ++ { CCI_REG8(0x39b5), 0xcd }, { CCI_REG8(0x39b6), 0xcd }, ++ { CCI_REG8(0x39b7), 0xcd }, { CCI_REG8(0x39b8), 0xcd }, ++ { CCI_REG8(0x39b9), 0xcd }, { CCI_REG8(0x39ba), 0xcd }, ++ { CCI_REG8(0x39bb), 0xcd }, { CCI_REG8(0x39bc), 0xcd }, ++ { CCI_REG8(0x39bd), 0xcd }, { CCI_REG8(0x39be), 0xcd }, ++ { CCI_REG8(0x39bf), 0xcd }, { CCI_REG8(0x39c0), 0xcd }, ++ { CCI_REG8(0x39c1), 0xcd }, { CCI_REG8(0x39c2), 0xcd }, ++ { CCI_REG8(0x39c3), 0xcd }, { CCI_REG8(0x39c4), 0xcd }, ++ { CCI_REG8(0x39c5), 0xcd }, { CCI_REG8(0x39c6), 0xcd }, ++ { CCI_REG8(0x39c7), 0xcd }, { CCI_REG8(0x39c8), 0xcd }, ++ { CCI_REG8(0x39c9), 0xcd }, { CCI_REG8(0x39ca), 0xcd }, ++ { CCI_REG8(0x39cb), 0xcd }, { CCI_REG8(0x39cc), 0xcd }, ++ { CCI_REG8(0x39cd), 0xcd }, { CCI_REG8(0x39ce), 0xcd }, ++ { CCI_REG8(0x39cf), 0xcd }, { CCI_REG8(0x39d0), 0xcd }, ++ { CCI_REG8(0x39d1), 0xcd }, { CCI_REG8(0x39d2), 0xcd }, ++ { CCI_REG8(0x39d3), 0xcd }, { CCI_REG8(0x39d4), 0xcd }, ++ { CCI_REG8(0x39d5), 0xcd }, { CCI_REG8(0x39d6), 0xcd }, ++ { CCI_REG8(0x39d7), 0xcd }, { CCI_REG8(0x39d8), 0xcd }, ++ { CCI_REG8(0x39d9), 0xcd }, { CCI_REG8(0x39da), 0xcd }, ++ { CCI_REG8(0x39db), 0xcd }, { CCI_REG8(0x39dc), 0xcd }, ++ { CCI_REG8(0x39dd), 0xcd }, { CCI_REG8(0x39de), 0xcd }, ++ { CCI_REG8(0x39df), 0xcd }, { CCI_REG8(0x39e0), 0xcd }, ++ { CCI_REG8(0x39e1), 0x40 }, { CCI_REG8(0x39e2), 0x40 }, ++ { CCI_REG8(0x39e3), 0x40 }, { CCI_REG8(0x39e4), 0x40 }, ++ { CCI_REG8(0x39e5), 0x40 }, { CCI_REG8(0x39e6), 0x40 }, ++ { CCI_REG8(0x39e7), 0x40 }, { CCI_REG8(0x39e8), 0x40 }, ++ { CCI_REG8(0x39e9), 0x40 }, { CCI_REG8(0x39ea), 0x40 }, ++ { CCI_REG8(0x39eb), 0x40 }, { CCI_REG8(0x39ec), 0x40 }, ++ { CCI_REG8(0x39ed), 0x40 }, { CCI_REG8(0x39ee), 0x40 }, ++ { CCI_REG8(0x39ef), 0x40 }, { CCI_REG8(0x39f0), 0x40 }, ++ { CCI_REG8(0x39f1), 0x40 }, { CCI_REG8(0x39f2), 0x40 }, ++ { CCI_REG8(0x39f3), 0x40 }, { CCI_REG8(0x39f4), 0x40 }, ++ { CCI_REG8(0x39f5), 0x40 }, { CCI_REG8(0x39f6), 0x40 }, ++ { CCI_REG8(0x39f7), 0x40 }, { CCI_REG8(0x39f8), 0x40 }, ++ { CCI_REG8(0x39f9), 0x40 }, { CCI_REG8(0x39fa), 0x40 }, ++ { CCI_REG8(0x39fb), 0x40 }, { CCI_REG8(0x39fc), 0x40 }, ++ { CCI_REG8(0x39fd), 0x40 }, { CCI_REG8(0x39fe), 0x40 }, ++ { CCI_REG8(0x39ff), 0x40 }, { CCI_REG8(0x3a00), 0x40 }, ++ { CCI_REG8(0x3a01), 0x40 }, { CCI_REG8(0x3a02), 0x40 }, ++ { CCI_REG8(0x3a03), 0x40 }, { CCI_REG8(0x3a04), 0x40 }, ++ { CCI_REG8(0x3a05), 0x40 }, { CCI_REG8(0x3a06), 0x40 }, ++ { CCI_REG8(0x3a07), 0x40 }, { CCI_REG8(0x3a08), 0x40 }, ++ { CCI_REG8(0x3a09), 0x40 }, { CCI_REG8(0x3a0a), 0x40 }, ++ { CCI_REG8(0x3a0b), 0x40 }, { CCI_REG8(0x3a0c), 0x40 }, ++ { CCI_REG8(0x3a0d), 0x40 }, { CCI_REG8(0x3a0e), 0x40 }, ++ { CCI_REG8(0x3a0f), 0x40 }, { CCI_REG8(0x3a10), 0x40 }, ++ { CCI_REG8(0x3a11), 0x40 }, { CCI_REG8(0x3a12), 0x40 }, ++ { CCI_REG8(0x3a13), 0x40 }, { CCI_REG8(0x3a14), 0x40 }, ++ { CCI_REG8(0x3a15), 0x40 }, { CCI_REG8(0x3a16), 0x40 }, ++ { CCI_REG8(0x3a17), 0x40 }, { CCI_REG8(0x3a18), 0x40 }, ++ { CCI_REG8(0x3a19), 0x40 }, { CCI_REG8(0x3a1a), 0x40 }, ++ { CCI_REG8(0x3a1b), 0x40 }, { CCI_REG8(0x3a1c), 0x40 }, ++ { CCI_REG8(0x3a1d), 0x40 }, { CCI_REG8(0x3a1e), 0x40 }, ++ { CCI_REG8(0x3a1f), 0x40 }, { CCI_REG8(0x3a20), 0x40 }, ++ { CCI_REG8(0x3a21), 0x40 }, { CCI_REG8(0x3a22), 0x40 }, ++ { CCI_REG8(0x3a23), 0x40 }, { CCI_REG8(0x3a24), 0x40 }, ++ { CCI_REG8(0x3a25), 0x40 }, { CCI_REG8(0x3a26), 0x40 }, ++ { CCI_REG8(0x3a27), 0x40 }, { CCI_REG8(0x3a28), 0x40 }, ++ { CCI_REG8(0x3a29), 0x40 }, { CCI_REG8(0x3a2a), 0x40 }, ++ { CCI_REG8(0x3a2b), 0x40 }, { CCI_REG8(0x3a2c), 0x40 }, ++ { CCI_REG8(0x3a2d), 0x40 }, { CCI_REG8(0x3a2e), 0x40 }, ++ { CCI_REG8(0x3a2f), 0x40 }, { CCI_REG8(0x3a30), 0x40 }, ++ { CCI_REG8(0x3a31), 0x40 }, { CCI_REG8(0x3a32), 0x40 }, ++ { CCI_REG8(0x3a33), 0x40 }, { CCI_REG8(0x3a34), 0x40 }, ++ { CCI_REG8(0x3a35), 0x40 }, { CCI_REG8(0x3a36), 0x40 }, ++ { CCI_REG8(0x3a37), 0x40 }, { CCI_REG8(0x3a38), 0x40 }, ++ { CCI_REG8(0x3a39), 0x40 }, { CCI_REG8(0x3a3a), 0x40 }, ++ { CCI_REG8(0x3a3b), 0xcd }, { CCI_REG8(0x3a3c), 0xcd }, ++ { CCI_REG8(0x3a3d), 0xcd }, { CCI_REG8(0x3a3e), 0xcd }, ++ { CCI_REG8(0x3a3f), 0xcd }, { CCI_REG8(0x3a40), 0xcd }, ++ { CCI_REG8(0x3a41), 0xcd }, { CCI_REG8(0x3a42), 0xcd }, ++ { CCI_REG8(0x3a43), 0xcd }, { CCI_REG8(0x3a44), 0xcd }, ++ { CCI_REG8(0x3a45), 0xcd }, { CCI_REG8(0x3a46), 0xcd }, ++ { CCI_REG8(0x3a47), 0xcd }, { CCI_REG8(0x3a48), 0xcd }, ++ { CCI_REG8(0x3a49), 0xcd }, { CCI_REG8(0x3a4a), 0xcd }, ++ { CCI_REG8(0x3a4b), 0xcd }, { CCI_REG8(0x3a4c), 0xcd }, ++ { CCI_REG8(0x3a4d), 0xcd }, { CCI_REG8(0x3a4e), 0xcd }, ++ { CCI_REG8(0x3a4f), 0xcd }, { CCI_REG8(0x3a50), 0xcd }, ++ { CCI_REG8(0x3a51), 0xcd }, { CCI_REG8(0x3a52), 0xcd }, ++ { CCI_REG8(0x3a53), 0xcd }, { CCI_REG8(0x3a54), 0xcd }, ++ { CCI_REG8(0x3a55), 0xcd }, { CCI_REG8(0x3a56), 0xcd }, ++ { CCI_REG8(0x3a57), 0xcd }, { CCI_REG8(0x3a58), 0xcd }, ++ { CCI_REG8(0x3a59), 0xcd }, { CCI_REG8(0x3a5a), 0xcd }, ++ { CCI_REG8(0x3a5b), 0xcd }, { CCI_REG8(0x3a5c), 0xcd }, ++ { CCI_REG8(0x3a5d), 0xcd }, { CCI_REG8(0x3a5e), 0xcd }, ++ { CCI_REG8(0x3a5f), 0xcd }, { CCI_REG8(0x3a60), 0xcd }, ++ { CCI_REG8(0x3a61), 0xcd }, { CCI_REG8(0x3a62), 0xcd }, ++ { CCI_REG8(0x3a63), 0xcd }, { CCI_REG8(0x3a64), 0xcd }, ++ { CCI_REG8(0x3a65), 0xcd }, { CCI_REG8(0x3a66), 0xcd }, ++ { CCI_REG8(0x3a67), 0xcd }, { CCI_REG8(0x3a68), 0xcd }, ++ { CCI_REG8(0x3a69), 0xcd }, { CCI_REG8(0x3a6a), 0xcd }, ++ { CCI_REG8(0x3a6b), 0xcd }, { CCI_REG8(0x3a6c), 0xcd }, ++ { CCI_REG8(0x3a6d), 0xcd }, { CCI_REG8(0x3a6e), 0xcd }, ++ { CCI_REG8(0x3a6f), 0xcd }, { CCI_REG8(0x3a70), 0xcd }, ++ { CCI_REG8(0x3a71), 0xcd }, { CCI_REG8(0x3a72), 0xcd }, ++ { CCI_REG8(0x3a73), 0xcd }, { CCI_REG8(0x3a74), 0xcd }, ++ { CCI_REG8(0x3a75), 0xcd }, { CCI_REG8(0x3a76), 0xcd }, ++ { CCI_REG8(0x3a77), 0xcd }, { CCI_REG8(0x3a78), 0xcd }, ++ { CCI_REG8(0x3a79), 0xcd }, { CCI_REG8(0x3a7a), 0xcd }, ++ { CCI_REG8(0x3a7b), 0xcd }, { CCI_REG8(0x3a7c), 0xcd }, ++ { CCI_REG8(0x3a7d), 0xcd }, { CCI_REG8(0x3a7e), 0xcd }, ++ { CCI_REG8(0x3a7f), 0xcd }, { CCI_REG8(0x3a80), 0xcd }, ++ { CCI_REG8(0x3a81), 0xcd }, { CCI_REG8(0x3a82), 0xcd }, ++ { CCI_REG8(0x3a83), 0xcd }, { CCI_REG8(0x3a84), 0xcd }, ++ { CCI_REG8(0x3a85), 0xcd }, { CCI_REG8(0x3a86), 0xcd }, ++ { CCI_REG8(0x3a87), 0xcd }, { CCI_REG8(0x3a88), 0xcd }, ++ { CCI_REG8(0x3a89), 0xcd }, { CCI_REG8(0x3a8a), 0xcd }, ++ { CCI_REG8(0x3a8b), 0xcd }, { CCI_REG8(0x3a8c), 0xcd }, ++ { CCI_REG8(0x3a8d), 0xcd }, { CCI_REG8(0x3a8e), 0xcd }, ++ { CCI_REG8(0x3a8f), 0xcd }, { CCI_REG8(0x3a90), 0xcd }, ++ { CCI_REG8(0x3a91), 0xcd }, { CCI_REG8(0x3a92), 0xcd }, ++ { CCI_REG8(0x3a93), 0xcd }, { CCI_REG8(0x3a94), 0xcd }, ++ { CCI_REG8(0x3a95), 0x40 }, { CCI_REG8(0x3a96), 0x40 }, ++ { CCI_REG8(0x3a97), 0x40 }, { CCI_REG8(0x3a98), 0x40 }, ++ { CCI_REG8(0x3a99), 0x40 }, { CCI_REG8(0x3a9a), 0x40 }, ++ { CCI_REG8(0x3a9b), 0x40 }, { CCI_REG8(0x3a9c), 0x40 }, ++ { CCI_REG8(0x3a9d), 0x40 }, { CCI_REG8(0x3a9e), 0x40 }, ++ { CCI_REG8(0x3a9f), 0x40 }, { CCI_REG8(0x3aa0), 0x40 }, ++ { CCI_REG8(0x3aa1), 0x40 }, { CCI_REG8(0x3aa2), 0x40 }, ++ { CCI_REG8(0x3aa3), 0x40 }, { CCI_REG8(0x3aa4), 0x40 }, ++ { CCI_REG8(0x3aa5), 0x40 }, { CCI_REG8(0x3aa6), 0x40 }, ++ { CCI_REG8(0x3aa7), 0x40 }, { CCI_REG8(0x3aa8), 0x40 }, ++ { CCI_REG8(0x3aa9), 0x40 }, { CCI_REG8(0x3aaa), 0x40 }, ++ { CCI_REG8(0x3aab), 0x40 }, { CCI_REG8(0x3aac), 0x40 }, ++ { CCI_REG8(0x3aad), 0x40 }, { CCI_REG8(0x3aae), 0x40 }, ++ { CCI_REG8(0x3aaf), 0x40 }, { CCI_REG8(0x3ab0), 0x40 }, ++ { CCI_REG8(0x3ab1), 0x40 }, { CCI_REG8(0x3ab2), 0x40 }, ++ { CCI_REG8(0x3ab3), 0x40 }, { CCI_REG8(0x3ab4), 0x40 }, ++ { CCI_REG8(0x3ab5), 0x40 }, { CCI_REG8(0x3ab6), 0x40 }, ++ { CCI_REG8(0x3ab7), 0x40 }, { CCI_REG8(0x3ab8), 0x40 }, ++ { CCI_REG8(0x3ab9), 0x40 }, { CCI_REG8(0x3aba), 0x40 }, ++ { CCI_REG8(0x3abb), 0x40 }, { CCI_REG8(0x3abc), 0x40 }, ++ { CCI_REG8(0x3abd), 0x40 }, { CCI_REG8(0x3abe), 0x40 }, ++ { CCI_REG8(0x3abf), 0x40 }, { CCI_REG8(0x3ac0), 0x40 }, ++ { CCI_REG8(0x3ac1), 0x40 }, { CCI_REG8(0x3ac2), 0x40 }, ++ { CCI_REG8(0x3ac3), 0x40 }, { CCI_REG8(0x3ac4), 0x40 }, ++ { CCI_REG8(0x3ac5), 0x40 }, { CCI_REG8(0x3ac6), 0x40 }, ++ { CCI_REG8(0x3ac7), 0x40 }, { CCI_REG8(0x3ac8), 0x40 }, ++ { CCI_REG8(0x3ac9), 0x40 }, { CCI_REG8(0x3aca), 0x40 }, ++ { CCI_REG8(0x3acb), 0x40 }, { CCI_REG8(0x3acc), 0x40 }, ++ { CCI_REG8(0x3acd), 0x40 }, { CCI_REG8(0x3ace), 0x40 }, ++ { CCI_REG8(0x3acf), 0x40 }, { CCI_REG8(0x3ad0), 0x40 }, ++ { CCI_REG8(0x3ad1), 0x40 }, { CCI_REG8(0x3ad2), 0x40 }, ++ { CCI_REG8(0x3ad3), 0x40 }, { CCI_REG8(0x3ad4), 0x40 }, ++ { CCI_REG8(0x3ad5), 0x40 }, { CCI_REG8(0x3ad6), 0x40 }, ++ { CCI_REG8(0x3ad7), 0x40 }, { CCI_REG8(0x3ad8), 0x40 }, ++ { CCI_REG8(0x3ad9), 0x40 }, { CCI_REG8(0x3ada), 0x40 }, ++ { CCI_REG8(0x3adb), 0x40 }, { CCI_REG8(0x3adc), 0x40 }, ++ { CCI_REG8(0x3add), 0x40 }, { CCI_REG8(0x3ade), 0x40 }, ++ { CCI_REG8(0x3adf), 0x40 }, { CCI_REG8(0x3ae0), 0x40 }, ++ { CCI_REG8(0x3ae1), 0x40 }, { CCI_REG8(0x3ae2), 0x40 }, ++ { CCI_REG8(0x3ae3), 0x40 }, { CCI_REG8(0x3ae4), 0x40 }, ++ { CCI_REG8(0x3ae5), 0x40 }, { CCI_REG8(0x3ae6), 0x40 }, ++ { CCI_REG8(0x3ae7), 0x40 }, { CCI_REG8(0x3ae8), 0x40 }, ++ { CCI_REG8(0x3ae9), 0x40 }, { CCI_REG8(0x3aea), 0x40 }, ++ { CCI_REG8(0x3aeb), 0x40 }, { CCI_REG8(0x3aec), 0x40 }, ++ { CCI_REG8(0x3aed), 0x40 }, { CCI_REG8(0x3aee), 0x40 }, ++ { CCI_REG8(0x3aef), 0xcd }, { CCI_REG8(0x3af0), 0xcd }, ++ { CCI_REG8(0x3af1), 0xcd }, { CCI_REG8(0x3af2), 0xcd }, ++ { CCI_REG8(0x3af3), 0xcd }, { CCI_REG8(0x3af4), 0xcd }, ++ { CCI_REG8(0x3af5), 0xcd }, { CCI_REG8(0x3af6), 0xcd }, ++ { CCI_REG8(0x3af7), 0xcd }, { CCI_REG8(0x3af8), 0xcd }, ++ { CCI_REG8(0x3af9), 0xcd }, { CCI_REG8(0x3afa), 0xcd }, ++ { CCI_REG8(0x3afb), 0xcd }, { CCI_REG8(0x3afc), 0xcd }, ++ { CCI_REG8(0x3afd), 0xcd }, { CCI_REG8(0x3afe), 0xcd }, ++ { CCI_REG8(0x3aff), 0xcd }, { CCI_REG8(0x3b00), 0xcd }, ++ { CCI_REG8(0x3b01), 0xcd }, { CCI_REG8(0x3b02), 0xcd }, ++ { CCI_REG8(0x3b03), 0xcd }, { CCI_REG8(0x3b04), 0xcd }, ++ { CCI_REG8(0x3b05), 0xcd }, { CCI_REG8(0x3b06), 0xcd }, ++ { CCI_REG8(0x3b07), 0xcd }, { CCI_REG8(0x3b08), 0xcd }, ++ { CCI_REG8(0x3b09), 0xcd }, { CCI_REG8(0x3b0a), 0xcd }, ++ { CCI_REG8(0x3b0b), 0xcd }, { CCI_REG8(0x3b0c), 0xcd }, ++ { CCI_REG8(0x3b0d), 0xcd }, { CCI_REG8(0x3b0e), 0xcd }, ++ { CCI_REG8(0x3b0f), 0xcd }, { CCI_REG8(0x3b10), 0xcd }, ++ { CCI_REG8(0x3b11), 0xcd }, { CCI_REG8(0x3b12), 0xcd }, ++ { CCI_REG8(0x3b13), 0xcd }, { CCI_REG8(0x3b14), 0xcd }, ++ { CCI_REG8(0x3b15), 0xcd }, { CCI_REG8(0x3b16), 0xcd }, ++ { CCI_REG8(0x3b17), 0xcd }, { CCI_REG8(0x3b18), 0xcd }, ++ { CCI_REG8(0x3b19), 0xcd }, { CCI_REG8(0x3b1a), 0xcd }, ++ { CCI_REG8(0x3b1b), 0xcd }, { CCI_REG8(0x3b1c), 0xcd }, ++ { CCI_REG8(0x3b1d), 0xcd }, { CCI_REG8(0x3b1e), 0xcd }, ++ { CCI_REG8(0x3b1f), 0xcd }, { CCI_REG8(0x3b20), 0xcd }, ++ { CCI_REG8(0x3b21), 0xcd }, { CCI_REG8(0x3b22), 0xcd }, ++ { CCI_REG8(0x3b23), 0xcd }, { CCI_REG8(0x3b24), 0xcd }, ++ { CCI_REG8(0x3b25), 0xcd }, { CCI_REG8(0x3b26), 0xcd }, ++ { CCI_REG8(0x3b27), 0xcd }, { CCI_REG8(0x3b28), 0xcd }, ++ { CCI_REG8(0x3b29), 0xcd }, { CCI_REG8(0x3b2a), 0xcd }, ++ { CCI_REG8(0x3b2b), 0xcd }, { CCI_REG8(0x3b2c), 0xcd }, ++ { CCI_REG8(0x3b2d), 0xcd }, { CCI_REG8(0x3b2e), 0xcd }, ++ { CCI_REG8(0x3b2f), 0xcd }, { CCI_REG8(0x3b30), 0xcd }, ++ { CCI_REG8(0x3b31), 0xcd }, { CCI_REG8(0x3b32), 0xcd }, ++ { CCI_REG8(0x3b33), 0xcd }, { CCI_REG8(0x3b34), 0xcd }, ++ { CCI_REG8(0x3b35), 0xcd }, { CCI_REG8(0x3b36), 0xcd }, ++ { CCI_REG8(0x3b37), 0xcd }, { CCI_REG8(0x3b38), 0xcd }, ++ { CCI_REG8(0x3b39), 0xcd }, { CCI_REG8(0x3b3a), 0xcd }, ++ { CCI_REG8(0x3b3b), 0xcd }, { CCI_REG8(0x3b3c), 0xcd }, ++ { CCI_REG8(0x3b3d), 0xcd }, { CCI_REG8(0x3b3e), 0xcd }, ++ { CCI_REG8(0x3b3f), 0xcd }, { CCI_REG8(0x3b40), 0xcd }, ++ { CCI_REG8(0x3b41), 0xcd }, { CCI_REG8(0x3b42), 0xcd }, ++ { CCI_REG8(0x3b43), 0xcd }, { CCI_REG8(0x3b44), 0xcd }, ++ { CCI_REG8(0x3b45), 0xcd }, { CCI_REG8(0x3b46), 0xcd }, ++ { CCI_REG8(0x3b47), 0xcd }, { CCI_REG8(0x3b48), 0xcd }, ++ { CCI_REG8(0x3b49), 0xcd }, { CCI_REG8(0x3b4a), 0xcd }, ++ { CCI_REG8(0x3b4b), 0xcd }, { CCI_REG8(0x3b4c), 0xcd }, ++ { CCI_REG8(0x3b4d), 0xcd }, { CCI_REG8(0x3b4e), 0xcd }, ++ { CCI_REG8(0x3b4f), 0xcd }, { CCI_REG8(0x3b50), 0xcd }, ++ { CCI_REG8(0x3b51), 0xcd }, { CCI_REG8(0x3b52), 0xcd }, ++ { CCI_REG8(0x3b53), 0xcd }, { CCI_REG8(0x3b54), 0xcd }, ++ { CCI_REG8(0x3b55), 0xcd }, { CCI_REG8(0x3b56), 0xcd }, ++ { CCI_REG8(0x3b57), 0xcd }, { CCI_REG8(0x3b58), 0xcd }, ++ { CCI_REG8(0x3b59), 0xcd }, { CCI_REG8(0x3b5a), 0xcd }, ++ { CCI_REG8(0x3b5b), 0xcd }, { CCI_REG8(0x3b5c), 0xcd }, ++ { CCI_REG8(0x3b5d), 0xcd }, { CCI_REG8(0x3b5e), 0xcd }, ++ { CCI_REG8(0x3b5f), 0xcd }, { CCI_REG8(0x3b60), 0xcd }, ++ { CCI_REG8(0x3b61), 0xcd }, { CCI_REG8(0x3b62), 0xcd }, ++ { CCI_REG8(0x3b63), 0xcd }, { CCI_REG8(0x3b64), 0xcd }, ++ { CCI_REG8(0x3b65), 0xcd }, { CCI_REG8(0x3b66), 0xcd }, ++ { CCI_REG8(0x3b67), 0xcd }, { CCI_REG8(0x3b68), 0xcd }, ++ { CCI_REG8(0x3b69), 0xcd }, { CCI_REG8(0x3b6a), 0xcd }, ++ { CCI_REG8(0x3b6b), 0xcd }, { CCI_REG8(0x3b6c), 0xcd }, ++ { CCI_REG8(0x3b6d), 0xcd }, { CCI_REG8(0x3b6e), 0xcd }, ++ { CCI_REG8(0x3b6f), 0xcd }, { CCI_REG8(0x3b70), 0xcd }, ++ { CCI_REG8(0x3b71), 0xcd }, { CCI_REG8(0x3b72), 0xcd }, ++ { CCI_REG8(0x3b73), 0xcd }, { CCI_REG8(0x3b74), 0xcd }, ++ { CCI_REG8(0x3b75), 0xcd }, { CCI_REG8(0x3b76), 0xcd }, ++ { CCI_REG8(0x3b77), 0xcd }, { CCI_REG8(0x3b78), 0xcd }, ++ { CCI_REG8(0x3b79), 0xcd }, { CCI_REG8(0x3b7a), 0xcd }, ++ { CCI_REG8(0x3b7b), 0xcd }, { CCI_REG8(0x3b7c), 0xcd }, ++ { CCI_REG8(0x3b7d), 0xcd }, { CCI_REG8(0x3b7e), 0xcd }, ++ { CCI_REG8(0x3b7f), 0xcd }, { CCI_REG8(0x3b80), 0xcd }, ++ { CCI_REG8(0x3b81), 0xcd }, { CCI_REG8(0x3b82), 0xcd }, ++ { CCI_REG8(0x3b83), 0xcd }, { CCI_REG8(0x3b84), 0xcd }, ++ { CCI_REG8(0x3b85), 0xcd }, { CCI_REG8(0x3b86), 0xcd }, ++ { CCI_REG8(0x3b87), 0xcd }, { CCI_REG8(0x3b88), 0xcd }, ++ { CCI_REG8(0x3b89), 0xcd }, { CCI_REG8(0x3b8a), 0xcd }, ++ { CCI_REG8(0x3b8b), 0xcd }, { CCI_REG8(0x3b8c), 0xcd }, ++ { CCI_REG8(0x3b8d), 0xcd }, { CCI_REG8(0x3b8e), 0xcd }, ++ { CCI_REG8(0x3b8f), 0xcd }, { CCI_REG8(0x3b90), 0xcd }, ++ { CCI_REG8(0x3b91), 0xcd }, { CCI_REG8(0x3b92), 0xcd }, ++ { CCI_REG8(0x3b93), 0xcd }, { CCI_REG8(0x3b94), 0xcd }, ++ { CCI_REG8(0x3b95), 0xcd }, { CCI_REG8(0x3b96), 0xcd }, ++ { CCI_REG8(0x3b97), 0xcd }, { CCI_REG8(0x3b98), 0xcd }, ++ { CCI_REG8(0x3b99), 0xcd }, { CCI_REG8(0x3b9a), 0xcd }, ++ { CCI_REG8(0x3b9b), 0xcd }, { CCI_REG8(0x3b9c), 0xcd }, ++ { CCI_REG8(0x3b9d), 0xcd }, { CCI_REG8(0x3b9e), 0xcd }, ++ { CCI_REG8(0x3b9f), 0xcd }, { CCI_REG8(0x3ba0), 0xcd }, ++ { CCI_REG8(0x3ba1), 0xcd }, { CCI_REG8(0x3ba2), 0xcd }, ++ { CCI_REG8(0x3ba3), 0xcd }, { CCI_REG8(0x3ba4), 0xcd }, ++ { CCI_REG8(0x3ba5), 0xcd }, { CCI_REG8(0x3ba6), 0xcd }, ++ { CCI_REG8(0x3ba7), 0xcd }, { CCI_REG8(0x3ba8), 0xcd }, ++ { CCI_REG8(0x3ba9), 0xcd }, { CCI_REG8(0x3baa), 0xcd }, ++ { CCI_REG8(0x3bab), 0xcd }, { CCI_REG8(0x3bac), 0xcd }, ++ { CCI_REG8(0x3bad), 0xcd }, { CCI_REG8(0x3bae), 0xcd }, ++ { CCI_REG8(0x3baf), 0xcd }, { CCI_REG8(0x3bb0), 0xcd }, ++ { CCI_REG8(0x3bb1), 0xcd }, { CCI_REG8(0x3bb2), 0xcd }, ++ { CCI_REG8(0x3bb3), 0xcd }, { CCI_REG8(0x3bb4), 0xcd }, ++ { CCI_REG8(0x3bb5), 0xcd }, { CCI_REG8(0x3bb6), 0xcd }, ++ { CCI_REG8(0x3bb7), 0xcd }, { CCI_REG8(0x3bb8), 0xcd }, ++ { CCI_REG8(0x3bb9), 0xcd }, { CCI_REG8(0x3bba), 0xcd }, ++ { CCI_REG8(0x3bbb), 0xcd }, { CCI_REG8(0x3bbc), 0xcd }, ++ { CCI_REG8(0x3bbd), 0xcd }, { CCI_REG8(0x3bbe), 0xcd }, ++ { CCI_REG8(0x3bbf), 0xcd }, { CCI_REG8(0x3bc0), 0xcd }, ++ { CCI_REG8(0x3bc1), 0xcd }, { CCI_REG8(0x3bc2), 0xcd }, ++ { CCI_REG8(0x3bc3), 0xcd }, { CCI_REG8(0x3bc4), 0xcd }, ++ { CCI_REG8(0x3bc5), 0xcd }, { CCI_REG8(0x3bc6), 0xcd }, ++ { CCI_REG8(0x3bc7), 0xcd }, { CCI_REG8(0x3bc8), 0xcd }, ++ { CCI_REG8(0x3bc9), 0xcd }, { CCI_REG8(0x3bca), 0xcd }, ++ { CCI_REG8(0x3bcb), 0xcd }, { CCI_REG8(0x3bcc), 0xcd }, ++ { CCI_REG8(0x3bcd), 0xcd }, { CCI_REG8(0x3bce), 0xcd }, ++ { CCI_REG8(0x3bcf), 0xcd }, { CCI_REG8(0x3bd0), 0xcd }, ++ { CCI_REG8(0x3bd1), 0xcd }, { CCI_REG8(0x3bd2), 0xcd }, ++ { CCI_REG8(0x3bd3), 0xcd }, { CCI_REG8(0x3bd4), 0xcd }, ++ { CCI_REG8(0x3bd5), 0xcd }, { CCI_REG8(0x3bd6), 0xcd }, ++ { CCI_REG8(0x3bd7), 0xcd }, { CCI_REG8(0x3bd8), 0xcd }, ++ { CCI_REG8(0x3bd9), 0xcd }, { CCI_REG8(0x3bda), 0xcd }, ++ { CCI_REG8(0x3bdb), 0xcd }, { CCI_REG8(0x3bdc), 0xcd }, ++ { CCI_REG8(0x3bdd), 0xcd }, { CCI_REG8(0x3bde), 0xcd }, ++ { CCI_REG8(0x3bdf), 0xcd }, { CCI_REG8(0x3be0), 0xcd }, ++ { CCI_REG8(0x3be1), 0xcd }, { CCI_REG8(0x3be2), 0xcd }, ++ { CCI_REG8(0x3be3), 0xcd }, { CCI_REG8(0x3be4), 0xcd }, ++ { CCI_REG8(0x3be5), 0xcd }, { CCI_REG8(0x3be6), 0xcd }, ++ { CCI_REG8(0x3be7), 0xcd }, { CCI_REG8(0x3be8), 0xcd }, ++ { CCI_REG8(0x3be9), 0xcd }, { CCI_REG8(0x3bea), 0xcd }, ++ { CCI_REG8(0x3beb), 0xcd }, { CCI_REG8(0x3bec), 0xcd }, ++ { CCI_REG8(0x3bed), 0xcd }, { CCI_REG8(0x3bee), 0xcd }, ++ { CCI_REG8(0x3bef), 0xcd }, { CCI_REG8(0x3bf0), 0xcd }, ++ { CCI_REG8(0x3bf1), 0xcd }, { CCI_REG8(0x3bf2), 0xcd }, ++ { CCI_REG8(0x3bf3), 0xcd }, { CCI_REG8(0x3bf4), 0xcd }, ++ { CCI_REG8(0x3bf5), 0xcd }, { CCI_REG8(0x3bf6), 0xcd }, ++ { CCI_REG8(0x3bf7), 0xcd }, { CCI_REG8(0x3bf8), 0xcd }, ++ { CCI_REG8(0x3bf9), 0xcd }, { CCI_REG8(0x3bfa), 0xcd }, ++ { CCI_REG8(0x3bfb), 0xcd }, { CCI_REG8(0x3bfc), 0xcd }, ++ { CCI_REG8(0x3bfd), 0xcd }, { CCI_REG8(0x3bfe), 0xcd }, ++ { CCI_REG8(0x3bff), 0xcd }, { CCI_REG8(0x3c00), 0xcd }, ++ { CCI_REG8(0x3c01), 0xcd }, { CCI_REG8(0x3c02), 0xcd }, ++ { CCI_REG8(0x3c03), 0xcd }, { CCI_REG8(0x3c04), 0xcd }, ++ { CCI_REG8(0x3c05), 0xcd }, { CCI_REG8(0x3c06), 0xcd }, ++ { CCI_REG8(0x3c07), 0xcd }, { CCI_REG8(0x3c08), 0xcd }, ++ { CCI_REG8(0x3c09), 0xcd }, { CCI_REG8(0x3c0a), 0xcd }, ++ { CCI_REG8(0x3c0b), 0xcd }, { CCI_REG8(0x3c0c), 0xcd }, ++ { CCI_REG8(0x3c0d), 0xcd }, { CCI_REG8(0x3c0e), 0xcd }, ++ { CCI_REG8(0x3c0f), 0xcd }, { CCI_REG8(0x3c10), 0xcd }, ++ { CCI_REG8(0x3c11), 0xcd }, { CCI_REG8(0x3c12), 0xcd }, ++ { CCI_REG8(0x3c13), 0xcd }, { CCI_REG8(0x3c14), 0xcd }, ++ { CCI_REG8(0x3c15), 0xcd }, { CCI_REG8(0x3c16), 0xcd }, ++ { CCI_REG8(0x3c17), 0xcd }, { CCI_REG8(0x3c18), 0xcd }, ++ { CCI_REG8(0x3c19), 0xcd }, { CCI_REG8(0x3c1a), 0xcd }, ++ { CCI_REG8(0x3c1b), 0xcd }, { CCI_REG8(0x3c1c), 0xcd }, ++ { CCI_REG8(0x3c1d), 0xcd }, { CCI_REG8(0x3c1e), 0xcd }, ++ { CCI_REG8(0x3c1f), 0xcd }, { CCI_REG8(0x3c20), 0xcd }, ++ { CCI_REG8(0x3c21), 0xcd }, { CCI_REG8(0x3c22), 0xcd }, ++ { CCI_REG8(0x3c23), 0xcd }, { CCI_REG8(0x3c24), 0xcd }, ++ { CCI_REG8(0x3c25), 0xcd }, { CCI_REG8(0x3c26), 0xcd }, ++ { CCI_REG8(0x3c27), 0xcd }, { CCI_REG8(0x3c28), 0xcd }, ++ { CCI_REG8(0x3c29), 0xcd }, { CCI_REG8(0x3c2a), 0xcd }, ++ { CCI_REG8(0x3c2b), 0xcd }, { CCI_REG8(0x3c2c), 0xcd }, ++ { CCI_REG8(0x3c2d), 0xcd }, { CCI_REG8(0x3c2e), 0xcd }, ++ { CCI_REG8(0x3c2f), 0xcd }, { CCI_REG8(0x3c30), 0xcd }, ++ { CCI_REG8(0x3c31), 0xcd }, { CCI_REG8(0x3c32), 0xcd }, ++ { CCI_REG8(0x3c33), 0xcd }, { CCI_REG8(0x3c34), 0xcd }, ++ { CCI_REG8(0x3c35), 0xcd }, { CCI_REG8(0x3c36), 0xcd }, ++ { CCI_REG8(0x3c37), 0xcd }, { CCI_REG8(0x3c38), 0xcd }, ++ { CCI_REG8(0x3c39), 0xcd }, { CCI_REG8(0x3c3a), 0xcd }, ++ { CCI_REG8(0x3c3b), 0xcd }, { CCI_REG8(0x3c3c), 0xcd }, ++ { CCI_REG8(0x3c3d), 0xcd }, { CCI_REG8(0x3c3e), 0xcd }, ++ { CCI_REG8(0x3c3f), 0xcd }, { CCI_REG8(0x3c40), 0xcd }, ++ { CCI_REG8(0x3c41), 0xcd }, { CCI_REG8(0x3c42), 0xcd }, ++ { CCI_REG8(0x3c43), 0xcd }, { CCI_REG8(0x3c44), 0xcd }, ++ { CCI_REG8(0x3c45), 0xcd }, { CCI_REG8(0x3c46), 0xcd }, ++ { CCI_REG8(0x3c47), 0xcd }, { CCI_REG8(0x3c48), 0xcd }, ++ { CCI_REG8(0x3c49), 0xcd }, { CCI_REG8(0x3c4a), 0xcd }, ++ { CCI_REG8(0x3c4b), 0xcd }, { CCI_REG8(0x3c4c), 0xcd }, ++ { CCI_REG8(0x3c4d), 0xcd }, { CCI_REG8(0x3c4e), 0xcd }, ++ { CCI_REG8(0x3c4f), 0xcd }, { CCI_REG8(0x3c50), 0xcd }, ++ { CCI_REG8(0x3c51), 0xcd }, { CCI_REG8(0x3c52), 0xcd }, ++ { CCI_REG8(0x3c53), 0xcd }, { CCI_REG8(0x3c54), 0xcd }, ++ { CCI_REG8(0x3c55), 0xcd }, { CCI_REG8(0x3c56), 0xcd }, ++ { CCI_REG8(0x3c57), 0xcd }, { CCI_REG8(0x3c58), 0xcd }, ++ { CCI_REG8(0x3c59), 0xcd }, { CCI_REG8(0x3c5a), 0xcd }, ++ { CCI_REG8(0x3c5b), 0xcd }, { CCI_REG8(0x3c5c), 0xcd }, ++ { CCI_REG8(0x3c5d), 0xcd }, { CCI_REG8(0x3c5e), 0xcd }, ++ { CCI_REG8(0x3c5f), 0xcd }, { CCI_REG8(0x3c60), 0xcd }, ++ { CCI_REG8(0x3c61), 0xcd }, { CCI_REG8(0x3c62), 0xcd }, ++ { CCI_REG8(0x3c63), 0xcd }, { CCI_REG8(0x3c64), 0xcd }, ++ { CCI_REG8(0x3c65), 0xcd }, { CCI_REG8(0x3c66), 0xcd }, ++ { CCI_REG8(0x3c67), 0xcd }, { CCI_REG8(0x3c68), 0xcd }, ++ { CCI_REG8(0x3c69), 0xcd }, { CCI_REG8(0x3c6a), 0xcd }, ++ { CCI_REG8(0x3c6b), 0xcd }, { CCI_REG8(0x3c6c), 0xcd }, ++ { CCI_REG8(0x3c6d), 0xcd }, { CCI_REG8(0x3c6e), 0xcd }, ++ { CCI_REG8(0x3c6f), 0xcd }, { CCI_REG8(0x3c70), 0xcd }, ++ { CCI_REG8(0x3c71), 0xcd }, { CCI_REG8(0x3c72), 0xcd }, ++ { CCI_REG8(0x3c73), 0xcd }, { CCI_REG8(0x3c74), 0xcd }, ++ { CCI_REG8(0x3c75), 0xcd }, { CCI_REG8(0x3c76), 0xcd }, ++ { CCI_REG8(0x3c77), 0xcd }, { CCI_REG8(0x3c78), 0xcd }, ++ { CCI_REG8(0x3c79), 0xcd }, { CCI_REG8(0x3c7a), 0xcd }, ++ { CCI_REG8(0x3c7b), 0xcd }, { CCI_REG8(0x3c7c), 0xcd }, ++ { CCI_REG8(0x3c7d), 0xcd }, { CCI_REG8(0x3c7e), 0xcd }, ++ { CCI_REG8(0x3c7f), 0xcd }, { CCI_REG8(0x3c80), 0xcd }, ++ { CCI_REG8(0x3c81), 0xcd }, { CCI_REG8(0x3c82), 0xcd }, ++ { CCI_REG8(0x3c83), 0xcd }, { CCI_REG8(0x3c84), 0xcd }, ++ { CCI_REG8(0x3c85), 0xcd }, { CCI_REG8(0x3c86), 0xcd }, ++ { CCI_REG8(0x3c87), 0xcd }, { CCI_REG8(0x3c88), 0xcd }, ++ { CCI_REG8(0x3c89), 0xcd }, { CCI_REG8(0x3c8a), 0xcd }, ++ { CCI_REG8(0x3c8b), 0xcd }, { CCI_REG8(0x3c8c), 0xcd }, ++ { CCI_REG8(0x3c8d), 0xcd }, { CCI_REG8(0x3c8e), 0xcd }, ++ { CCI_REG8(0x3c8f), 0xcd }, { CCI_REG8(0x3c90), 0xcd }, ++ { CCI_REG8(0x3c91), 0xcd }, { CCI_REG8(0x3c92), 0xcd }, ++ { CCI_REG8(0x3c93), 0xcd }, { CCI_REG8(0x3c94), 0xcd }, ++ { CCI_REG8(0x3c95), 0xcd }, { CCI_REG8(0x3c96), 0xcd }, ++ { CCI_REG8(0x3c97), 0xcd }, { CCI_REG8(0x3c98), 0xcd }, ++ { CCI_REG8(0x3c99), 0xcd }, { CCI_REG8(0x3c9a), 0xcd }, ++ { CCI_REG8(0x3c9b), 0xcd }, { CCI_REG8(0x3c9c), 0xcd }, ++ { CCI_REG8(0x3c9d), 0xcd }, { CCI_REG8(0x3c9e), 0xcd }, ++ { CCI_REG8(0x3c9f), 0xcd }, { CCI_REG8(0x3ca0), 0xcd }, ++ { CCI_REG8(0x3ca1), 0xcd }, { CCI_REG8(0x3ca2), 0xcd }, ++ { CCI_REG8(0x3ca3), 0xcd }, { CCI_REG8(0x3ca4), 0xcd }, ++ { CCI_REG8(0x3ca5), 0xcd }, { CCI_REG8(0x3ca6), 0xcd }, ++ { CCI_REG8(0x3ca7), 0xcd }, { CCI_REG8(0x3ca8), 0xcd }, ++ { CCI_REG8(0x3ca9), 0xcd }, { CCI_REG8(0x3caa), 0xcd }, ++ { CCI_REG8(0x3cab), 0xcd }, { CCI_REG8(0x3cac), 0xcd }, ++ { CCI_REG8(0x3cad), 0xcd }, { CCI_REG8(0x3cae), 0xcd }, ++ { CCI_REG8(0x3caf), 0xcd }, { CCI_REG8(0x3cb0), 0xcd }, ++ { CCI_REG8(0x3cb1), 0x40 }, { CCI_REG8(0x3cb2), 0x40 }, ++ { CCI_REG8(0x3cb3), 0x40 }, { CCI_REG8(0x3cb4), 0x40 }, ++ { CCI_REG8(0x3cb5), 0x40 }, { CCI_REG8(0x3cb6), 0x40 }, ++ { CCI_REG8(0x3cb7), 0x40 }, { CCI_REG8(0x3cb8), 0x40 }, ++ { CCI_REG8(0x3cb9), 0x40 }, { CCI_REG8(0x3cba), 0x40 }, ++ { CCI_REG8(0x3cbb), 0x40 }, { CCI_REG8(0x3cbc), 0x40 }, ++ { CCI_REG8(0x3cbd), 0x40 }, { CCI_REG8(0x3cbe), 0x40 }, ++ { CCI_REG8(0x3cbf), 0x40 }, { CCI_REG8(0x3cc0), 0x40 }, ++ { CCI_REG8(0x3cc1), 0x40 }, { CCI_REG8(0x3cc2), 0x40 }, ++ { CCI_REG8(0x3cc3), 0x40 }, { CCI_REG8(0x3cc4), 0x40 }, ++ { CCI_REG8(0x3cc5), 0x40 }, { CCI_REG8(0x3cc6), 0x40 }, ++ { CCI_REG8(0x3cc7), 0x40 }, { CCI_REG8(0x3cc8), 0x40 }, ++ { CCI_REG8(0x3cc9), 0x40 }, { CCI_REG8(0x3cca), 0x40 }, ++ { CCI_REG8(0x3ccb), 0x40 }, { CCI_REG8(0x3ccc), 0x40 }, ++ { CCI_REG8(0x3ccd), 0x40 }, { CCI_REG8(0x3cce), 0x40 }, ++ { CCI_REG8(0x3ccf), 0x40 }, { CCI_REG8(0x3cd0), 0x40 }, ++ { CCI_REG8(0x3cd1), 0x40 }, { CCI_REG8(0x3cd2), 0x40 }, ++ { CCI_REG8(0x3cd3), 0x40 }, { CCI_REG8(0x3cd4), 0x40 }, ++ { CCI_REG8(0x3cd5), 0x40 }, { CCI_REG8(0x3cd6), 0x40 }, ++ { CCI_REG8(0x3cd7), 0x40 }, { CCI_REG8(0x3cd8), 0x40 }, ++ { CCI_REG8(0x3cd9), 0x40 }, { CCI_REG8(0x3cda), 0x40 }, ++ { CCI_REG8(0x3cdb), 0x40 }, { CCI_REG8(0x3cdc), 0x40 }, ++ { CCI_REG8(0x3cdd), 0x40 }, { CCI_REG8(0x3cde), 0x40 }, ++ { CCI_REG8(0x3cdf), 0x40 }, { CCI_REG8(0x3ce0), 0x40 }, ++ { CCI_REG8(0x3ce1), 0x40 }, { CCI_REG8(0x3ce2), 0x40 }, ++ { CCI_REG8(0x3ce3), 0x40 }, { CCI_REG8(0x3ce4), 0x40 }, ++ { CCI_REG8(0x3ce5), 0x40 }, { CCI_REG8(0x3ce6), 0x40 }, ++ { CCI_REG8(0x3ce7), 0x40 }, { CCI_REG8(0x3ce8), 0x40 }, ++ { CCI_REG8(0x3ce9), 0x40 }, { CCI_REG8(0x3cea), 0x40 }, ++ { CCI_REG8(0x3ceb), 0x40 }, { CCI_REG8(0x3cec), 0x40 }, ++ { CCI_REG8(0x3ced), 0x40 }, { CCI_REG8(0x3cee), 0x40 }, ++ { CCI_REG8(0x3cef), 0x40 }, { CCI_REG8(0x3cf0), 0x40 }, ++ { CCI_REG8(0x3cf1), 0x40 }, { CCI_REG8(0x3cf2), 0x40 }, ++ { CCI_REG8(0x3cf3), 0x40 }, { CCI_REG8(0x3cf4), 0x40 }, ++ { CCI_REG8(0x3cf5), 0x40 }, { CCI_REG8(0x3cf6), 0x40 }, ++ { CCI_REG8(0x3cf7), 0x40 }, { CCI_REG8(0x3cf8), 0x40 }, ++ { CCI_REG8(0x3cf9), 0x40 }, { CCI_REG8(0x3cfa), 0x40 }, ++ { CCI_REG8(0x3cfb), 0x40 }, { CCI_REG8(0x3cfc), 0x40 }, ++ { CCI_REG8(0x3cfd), 0x40 }, { CCI_REG8(0x3cfe), 0x40 }, ++ { CCI_REG8(0x3cff), 0x40 }, { CCI_REG8(0x3d00), 0x40 }, ++ { CCI_REG8(0x3d01), 0x40 }, { CCI_REG8(0x3d02), 0x40 }, ++ { CCI_REG8(0x3d03), 0x40 }, { CCI_REG8(0x3d04), 0x40 }, ++ { CCI_REG8(0x3d05), 0x40 }, { CCI_REG8(0x3d06), 0x40 }, ++ { CCI_REG8(0x3d07), 0x40 }, { CCI_REG8(0x3d08), 0x40 }, ++ { CCI_REG8(0x3d09), 0x40 }, { CCI_REG8(0x3d0a), 0x40 }, ++ { CCI_REG8(0x3d0b), 0xcd }, { CCI_REG8(0x3d0c), 0xcd }, ++ { CCI_REG8(0x3d0d), 0xcd }, { CCI_REG8(0x3d0e), 0xcd }, ++ { CCI_REG8(0x3d0f), 0xcd }, { CCI_REG8(0x3d10), 0xcd }, ++ { CCI_REG8(0x3d11), 0xcd }, { CCI_REG8(0x3d12), 0xcd }, ++ { CCI_REG8(0x3d13), 0xcd }, { CCI_REG8(0x3d14), 0xcd }, ++ { CCI_REG8(0x3d15), 0xcd }, { CCI_REG8(0x3d16), 0xcd }, ++ { CCI_REG8(0x3d17), 0xcd }, { CCI_REG8(0x3d18), 0xcd }, ++ { CCI_REG8(0x3d19), 0xcd }, { CCI_REG8(0x3d1a), 0xcd }, ++ { CCI_REG8(0x3d1b), 0xcd }, { CCI_REG8(0x3d1c), 0xcd }, ++ { CCI_REG8(0x3d1d), 0xcd }, { CCI_REG8(0x3d1e), 0xcd }, ++ { CCI_REG8(0x3d1f), 0xcd }, { CCI_REG8(0x3d20), 0xcd }, ++ { CCI_REG8(0x3d21), 0xcd }, { CCI_REG8(0x3d22), 0xcd }, ++ { CCI_REG8(0x3d23), 0xcd }, { CCI_REG8(0x3d24), 0xcd }, ++ { CCI_REG8(0x3d25), 0xcd }, { CCI_REG8(0x3d26), 0xcd }, ++ { CCI_REG8(0x3d27), 0xcd }, { CCI_REG8(0x3d28), 0xcd }, ++ { CCI_REG8(0x3d29), 0xcd }, { CCI_REG8(0x3d2a), 0xcd }, ++ { CCI_REG8(0x3d2b), 0xcd }, { CCI_REG8(0x3d2c), 0xcd }, ++ { CCI_REG8(0x3d2d), 0xcd }, { CCI_REG8(0x3d2e), 0xcd }, ++ { CCI_REG8(0x3d2f), 0xcd }, { CCI_REG8(0x3d30), 0xcd }, ++ { CCI_REG8(0x3d31), 0xcd }, { CCI_REG8(0x3d32), 0xcd }, ++ { CCI_REG8(0x3d33), 0xcd }, { CCI_REG8(0x3d34), 0xcd }, ++ { CCI_REG8(0x3d35), 0xcd }, { CCI_REG8(0x3d36), 0xcd }, ++ { CCI_REG8(0x3d37), 0xcd }, { CCI_REG8(0x3d38), 0xcd }, ++ { CCI_REG8(0x3d39), 0xcd }, { CCI_REG8(0x3d3a), 0xcd }, ++ { CCI_REG8(0x3d3b), 0xcd }, { CCI_REG8(0x3d3c), 0xcd }, ++ { CCI_REG8(0x3d3d), 0xcd }, { CCI_REG8(0x3d3e), 0xcd }, ++ { CCI_REG8(0x3d3f), 0xcd }, { CCI_REG8(0x3d40), 0xcd }, ++ { CCI_REG8(0x3d41), 0xcd }, { CCI_REG8(0x3d42), 0xcd }, ++ { CCI_REG8(0x3d43), 0xcd }, { CCI_REG8(0x3d44), 0xcd }, ++ { CCI_REG8(0x3d45), 0xcd }, { CCI_REG8(0x3d46), 0xcd }, ++ { CCI_REG8(0x3d47), 0xcd }, { CCI_REG8(0x3d48), 0xcd }, ++ { CCI_REG8(0x3d49), 0xcd }, { CCI_REG8(0x3d4a), 0xcd }, ++ { CCI_REG8(0x3d4b), 0xcd }, { CCI_REG8(0x3d4c), 0xcd }, ++ { CCI_REG8(0x3d4d), 0xcd }, { CCI_REG8(0x3d4e), 0xcd }, ++ { CCI_REG8(0x3d4f), 0xcd }, { CCI_REG8(0x3d50), 0xcd }, ++ { CCI_REG8(0x3d51), 0xcd }, { CCI_REG8(0x3d52), 0xcd }, ++ { CCI_REG8(0x3d53), 0xcd }, { CCI_REG8(0x3d54), 0xcd }, ++ { CCI_REG8(0x3d55), 0xcd }, { CCI_REG8(0x3d56), 0xcd }, ++ { CCI_REG8(0x3d57), 0xcd }, { CCI_REG8(0x3d58), 0xcd }, ++ { CCI_REG8(0x3d59), 0xcd }, { CCI_REG8(0x3d5a), 0xcd }, ++ { CCI_REG8(0x3d5b), 0xcd }, { CCI_REG8(0x3d5c), 0xcd }, ++ { CCI_REG8(0x3d5d), 0xcd }, { CCI_REG8(0x3d5e), 0xcd }, ++ { CCI_REG8(0x3d5f), 0xcd }, { CCI_REG8(0x3d60), 0xcd }, ++ { CCI_REG8(0x3d61), 0xcd }, { CCI_REG8(0x3d62), 0xcd }, ++ { CCI_REG8(0x3d63), 0xcd }, { CCI_REG8(0x3d64), 0xcd }, ++ { CCI_REG8(0x3d65), 0x40 }, { CCI_REG8(0x3d66), 0x40 }, ++ { CCI_REG8(0x3d67), 0x40 }, { CCI_REG8(0x3d68), 0x40 }, ++ { CCI_REG8(0x3d69), 0x40 }, { CCI_REG8(0x3d6a), 0x40 }, ++ { CCI_REG8(0x3d6b), 0x40 }, { CCI_REG8(0x3d6c), 0x40 }, ++ { CCI_REG8(0x3d6d), 0x40 }, { CCI_REG8(0x3d6e), 0x40 }, ++ { CCI_REG8(0x3d6f), 0x40 }, { CCI_REG8(0x3d70), 0x40 }, ++ { CCI_REG8(0x3d71), 0x40 }, { CCI_REG8(0x3d72), 0x40 }, ++ { CCI_REG8(0x3d73), 0x40 }, { CCI_REG8(0x3d74), 0x40 }, ++ { CCI_REG8(0x3d75), 0x40 }, { CCI_REG8(0x3d76), 0x40 }, ++ { CCI_REG8(0x3d77), 0x40 }, { CCI_REG8(0x3d78), 0x40 }, ++ { CCI_REG8(0x3d79), 0x40 }, { CCI_REG8(0x3d7a), 0x40 }, ++ { CCI_REG8(0x3d7b), 0x40 }, { CCI_REG8(0x3d7c), 0x40 }, ++ { CCI_REG8(0x3d7d), 0x40 }, { CCI_REG8(0x3d7e), 0x40 }, ++ { CCI_REG8(0x3d7f), 0x40 }, { CCI_REG8(0x3d80), 0x40 }, ++ { CCI_REG8(0x3d81), 0x40 }, { CCI_REG8(0x3d82), 0x40 }, ++ { CCI_REG8(0x3d83), 0x40 }, { CCI_REG8(0x3d84), 0x40 }, ++ { CCI_REG8(0x3d85), 0x40 }, { CCI_REG8(0x3d86), 0x40 }, ++ { CCI_REG8(0x3d87), 0x40 }, { CCI_REG8(0x3d88), 0x40 }, ++ { CCI_REG8(0x3d89), 0x40 }, { CCI_REG8(0x3d8a), 0x40 }, ++ { CCI_REG8(0x3d8b), 0x40 }, { CCI_REG8(0x3d8c), 0x40 }, ++ { CCI_REG8(0x3d8d), 0x40 }, { CCI_REG8(0x3d8e), 0x40 }, ++ { CCI_REG8(0x3d8f), 0x40 }, { CCI_REG8(0x3d90), 0x40 }, ++ { CCI_REG8(0x3d91), 0x40 }, { CCI_REG8(0x3d92), 0x40 }, ++ { CCI_REG8(0x3d93), 0x40 }, { CCI_REG8(0x3d94), 0x40 }, ++ { CCI_REG8(0x3d95), 0x40 }, { CCI_REG8(0x3d96), 0x40 }, ++ { CCI_REG8(0x3d97), 0x40 }, { CCI_REG8(0x3d98), 0x40 }, ++ { CCI_REG8(0x3d99), 0x40 }, { CCI_REG8(0x3d9a), 0x40 }, ++ { CCI_REG8(0x3d9b), 0x40 }, { CCI_REG8(0x3d9c), 0x40 }, ++ { CCI_REG8(0x3d9d), 0x40 }, { CCI_REG8(0x3d9e), 0x40 }, ++ { CCI_REG8(0x3d9f), 0x40 }, { CCI_REG8(0x3da0), 0x40 }, ++ { CCI_REG8(0x3da1), 0x40 }, { CCI_REG8(0x3da2), 0x40 }, ++ { CCI_REG8(0x3da3), 0x40 }, { CCI_REG8(0x3da4), 0x40 }, ++ { CCI_REG8(0x3da5), 0x40 }, { CCI_REG8(0x3da6), 0x40 }, ++ { CCI_REG8(0x3da7), 0x40 }, { CCI_REG8(0x3da8), 0x40 }, ++ { CCI_REG8(0x3da9), 0x40 }, { CCI_REG8(0x3daa), 0x40 }, ++ { CCI_REG8(0x3dab), 0x40 }, { CCI_REG8(0x3dac), 0x40 }, ++ { CCI_REG8(0x3dad), 0x40 }, { CCI_REG8(0x3dae), 0x40 }, ++ { CCI_REG8(0x3daf), 0x40 }, { CCI_REG8(0x3db0), 0x40 }, ++ { CCI_REG8(0x3db1), 0x40 }, { CCI_REG8(0x3db2), 0x40 }, ++ { CCI_REG8(0x3db3), 0x40 }, { CCI_REG8(0x3db4), 0x40 }, ++ { CCI_REG8(0x3db5), 0x40 }, { CCI_REG8(0x3db6), 0x40 }, ++ { CCI_REG8(0x3db7), 0x40 }, { CCI_REG8(0x3db8), 0x40 }, ++ { CCI_REG8(0x3db9), 0x40 }, { CCI_REG8(0x3dba), 0x40 }, ++ { CCI_REG8(0x3dbb), 0x40 }, { CCI_REG8(0x3dbc), 0x40 }, ++ { CCI_REG8(0x3dbd), 0x40 }, { CCI_REG8(0x3dbe), 0x40 }, ++ { CCI_REG8(0x3dbf), 0xcd }, { CCI_REG8(0x3dc0), 0xcd }, ++ { CCI_REG8(0x3dc1), 0xcd }, { CCI_REG8(0x3dc2), 0xcd }, ++ { CCI_REG8(0x3dc3), 0xcd }, { CCI_REG8(0x3dc4), 0xcd }, ++ { CCI_REG8(0x3dc5), 0xcd }, { CCI_REG8(0x3dc6), 0xcd }, ++ { CCI_REG8(0x3dc7), 0xcd }, { CCI_REG8(0x3dc8), 0xcd }, ++ { CCI_REG8(0x3dc9), 0xcd }, { CCI_REG8(0x3dca), 0xcd }, ++ { CCI_REG8(0x3dcb), 0xcd }, { CCI_REG8(0x3dcc), 0xcd }, ++ { CCI_REG8(0x3dcd), 0xcd }, { CCI_REG8(0x3dce), 0xcd }, ++ { CCI_REG8(0x3dcf), 0xcd }, { CCI_REG8(0x3dd0), 0xcd }, ++ { CCI_REG8(0x3dd1), 0xcd }, { CCI_REG8(0x3dd2), 0xcd }, ++ { CCI_REG8(0x3dd3), 0xcd }, { CCI_REG8(0x3dd4), 0xcd }, ++ { CCI_REG8(0x3dd5), 0xcd }, { CCI_REG8(0x3dd6), 0xcd }, ++ { CCI_REG8(0x3dd7), 0xcd }, { CCI_REG8(0x3dd8), 0xcd }, ++ { CCI_REG8(0x3dd9), 0xcd }, { CCI_REG8(0x3dda), 0xcd }, ++ { CCI_REG8(0x3ddb), 0xcd }, { CCI_REG8(0x3ddc), 0xcd }, ++ { CCI_REG8(0x3ddd), 0xcd }, { CCI_REG8(0x3dde), 0xcd }, ++ { CCI_REG8(0x3ddf), 0xcd }, { CCI_REG8(0x3de0), 0xcd }, ++ { CCI_REG8(0x3de1), 0xcd }, { CCI_REG8(0x3de2), 0xcd }, ++ { CCI_REG8(0x3de3), 0xcd }, { CCI_REG8(0x3de4), 0xcd }, ++ { CCI_REG8(0x3de5), 0xcd }, { CCI_REG8(0x3de6), 0xcd }, ++ { CCI_REG8(0x3de7), 0xcd }, { CCI_REG8(0x3de8), 0xcd }, ++ { CCI_REG8(0x3de9), 0xcd }, { CCI_REG8(0x3dea), 0xcd }, ++ { CCI_REG8(0x3deb), 0xcd }, { CCI_REG8(0x3dec), 0xcd }, ++ { CCI_REG8(0x3ded), 0xcd }, { CCI_REG8(0x3dee), 0xcd }, ++ { CCI_REG8(0x3def), 0xcd }, { CCI_REG8(0x3df0), 0xcd }, ++ { CCI_REG8(0x3df1), 0xcd }, { CCI_REG8(0x3df2), 0xcd }, ++ { CCI_REG8(0x3df3), 0xcd }, { CCI_REG8(0x3df4), 0xcd }, ++ { CCI_REG8(0x3df5), 0xcd }, { CCI_REG8(0x3df6), 0xcd }, ++ { CCI_REG8(0x3df7), 0xcd }, { CCI_REG8(0x3df8), 0xcd }, ++ { CCI_REG8(0x3df9), 0xcd }, { CCI_REG8(0x3dfa), 0xcd }, ++ { CCI_REG8(0x3dfb), 0xcd }, { CCI_REG8(0x3dfc), 0xcd }, ++ { CCI_REG8(0x3dfd), 0xcd }, { CCI_REG8(0x3dfe), 0xcd }, ++ { CCI_REG8(0x3dff), 0xcd }, { CCI_REG8(0x3e00), 0xcd }, ++ { CCI_REG8(0x3e01), 0xcd }, { CCI_REG8(0x3e02), 0xcd }, ++ { CCI_REG8(0x3e03), 0xcd }, { CCI_REG8(0x3e04), 0xcd }, ++ { CCI_REG8(0x3e05), 0xcd }, { CCI_REG8(0x3e06), 0xcd }, ++ { CCI_REG8(0x3e07), 0xcd }, { CCI_REG8(0x3e08), 0xcd }, ++ { CCI_REG8(0x3e09), 0xcd }, { CCI_REG8(0x3e0a), 0xcd }, ++ { CCI_REG8(0x3e0b), 0xcd }, { CCI_REG8(0x3e0c), 0xcd }, ++ { CCI_REG8(0x3e0d), 0xcd }, { CCI_REG8(0x3e0e), 0xcd }, ++ { CCI_REG8(0x3e0f), 0xcd }, { CCI_REG8(0x3e10), 0xcd }, ++ { CCI_REG8(0x3e11), 0xcd }, { CCI_REG8(0x3e12), 0xcd }, ++ { CCI_REG8(0x3e13), 0xcd }, { CCI_REG8(0x3e14), 0xcd }, ++ { CCI_REG8(0x3e15), 0xcd }, { CCI_REG8(0x3e16), 0xcd }, ++ { CCI_REG8(0x3e17), 0xcd }, { CCI_REG8(0x3e18), 0xcd }, ++ { CCI_REG8(0x3e19), 0xcd }, { CCI_REG8(0x3e1a), 0xcd }, ++ { CCI_REG8(0x3e1b), 0xcd }, { CCI_REG8(0x3e1c), 0xcd }, ++ { CCI_REG8(0x3e1d), 0xcd }, { CCI_REG8(0x3e1e), 0xcd }, ++ { CCI_REG8(0x3e1f), 0xcd }, { CCI_REG8(0x3e20), 0xcd }, ++ { CCI_REG8(0x3e21), 0xcd }, { CCI_REG8(0x3e22), 0xcd }, ++ { CCI_REG8(0x3e23), 0xcd }, { CCI_REG8(0x3e24), 0xcd }, ++ { CCI_REG8(0x3e25), 0xcd }, { CCI_REG8(0x3e26), 0xcd }, ++ { CCI_REG8(0x3e27), 0xcd }, { CCI_REG8(0x3e28), 0xcd }, ++ { CCI_REG8(0x3e29), 0xcd }, { CCI_REG8(0x3e2a), 0xcd }, ++ { CCI_REG8(0x3e2b), 0xcd }, { CCI_REG8(0x3e2c), 0xcd }, ++ { CCI_REG8(0x3e2d), 0xcd }, { CCI_REG8(0x3e2e), 0xcd }, ++ { CCI_REG8(0x3e2f), 0xcd }, { CCI_REG8(0x3e30), 0xcd }, ++ { CCI_REG8(0x3e31), 0xcd }, { CCI_REG8(0x3e32), 0xcd }, ++ { CCI_REG8(0x3e33), 0xcd }, { CCI_REG8(0x3e34), 0xcd }, ++ { CCI_REG8(0x3e35), 0xcd }, { CCI_REG8(0x3e36), 0xcd }, ++ { CCI_REG8(0x3e37), 0xcd }, { CCI_REG8(0x3e38), 0xcd }, ++ { CCI_REG8(0x3e39), 0xcd }, { CCI_REG8(0x3e3a), 0xcd }, ++ { CCI_REG8(0x3e3b), 0xcd }, { CCI_REG8(0x3e3c), 0xcd }, ++ { CCI_REG8(0x3e3d), 0xcd }, { CCI_REG8(0x3e3e), 0xcd }, ++ { CCI_REG8(0x3e3f), 0xcd }, { CCI_REG8(0x3e40), 0xcd }, ++ { CCI_REG8(0x3e41), 0xcd }, { CCI_REG8(0x3e42), 0xcd }, ++ { CCI_REG8(0x3e43), 0xcd }, { CCI_REG8(0x3e44), 0xcd }, ++ { CCI_REG8(0x3e45), 0xcd }, { CCI_REG8(0x3e46), 0xcd }, ++ { CCI_REG8(0x3e47), 0xcd }, { CCI_REG8(0x3e48), 0xcd }, ++ { CCI_REG8(0x3e49), 0xcd }, { CCI_REG8(0x3e4a), 0xcd }, ++ { CCI_REG8(0x3e4b), 0xcd }, { CCI_REG8(0x3e4c), 0xcd }, ++ { CCI_REG8(0x3e4d), 0xcd }, { CCI_REG8(0x3e4e), 0xcd }, ++ { CCI_REG8(0x3e4f), 0xcd }, { CCI_REG8(0x3e50), 0xcd }, ++ { CCI_REG8(0x3e51), 0xcd }, { CCI_REG8(0x3e52), 0xcd }, ++ { CCI_REG8(0x3e53), 0xcd }, { CCI_REG8(0x3e54), 0xcd }, ++ { CCI_REG8(0x3e55), 0xcd }, { CCI_REG8(0x3e56), 0xcd }, ++ { CCI_REG8(0x3e57), 0xcd }, { CCI_REG8(0x3e58), 0xcd }, ++ { CCI_REG8(0x3e59), 0xcd }, { CCI_REG8(0x3e5a), 0xcd }, ++ { CCI_REG8(0x3e5b), 0xcd }, { CCI_REG8(0x3e5c), 0xcd }, ++ { CCI_REG8(0x3e5d), 0xcd }, { CCI_REG8(0x3e5e), 0xcd }, ++ { CCI_REG8(0x3e5f), 0xcd }, { CCI_REG8(0x3e60), 0xcd }, ++ { CCI_REG8(0x3e61), 0xcd }, { CCI_REG8(0x3e62), 0xcd }, ++ { CCI_REG8(0x3e63), 0xcd }, { CCI_REG8(0x3e64), 0xcd }, ++ { CCI_REG8(0x3e65), 0xcd }, { CCI_REG8(0x3e66), 0xcd }, ++ { CCI_REG8(0x3e67), 0xcd }, { CCI_REG8(0x3e68), 0xcd }, ++ { CCI_REG8(0x3e69), 0xcd }, { CCI_REG8(0x3e6a), 0xcd }, ++ { CCI_REG8(0x3e6b), 0xcd }, { CCI_REG8(0x3e6c), 0xcd }, ++ { CCI_REG8(0x3e6d), 0xcd }, { CCI_REG8(0x3e6e), 0xcd }, ++ { CCI_REG8(0x3e6f), 0xcd }, { CCI_REG8(0x3e70), 0xcd }, ++ { CCI_REG8(0x3e71), 0xcd }, { CCI_REG8(0x3e72), 0xcd }, ++ { CCI_REG8(0x3e73), 0xcd }, { CCI_REG8(0x3e74), 0xcd }, ++ { CCI_REG8(0x3e75), 0xcd }, { CCI_REG8(0x3e76), 0xcd }, ++ { CCI_REG8(0x3e77), 0xcd }, { CCI_REG8(0x3e78), 0xcd }, ++ { CCI_REG8(0x3e79), 0xcd }, { CCI_REG8(0x3e7a), 0xcd }, ++ { CCI_REG8(0x3e7b), 0xcd }, { CCI_REG8(0x3e7c), 0xcd }, ++ { CCI_REG8(0x3e7d), 0xcd }, { CCI_REG8(0x3e7e), 0xcd }, ++ { CCI_REG8(0x3e7f), 0xcd }, { CCI_REG8(0x3e80), 0xcd }, ++ { CCI_REG8(0x3e81), 0xcd }, { CCI_REG8(0x3e82), 0xcd }, ++ { CCI_REG8(0x3e83), 0xcd }, { CCI_REG8(0x3e84), 0xcd }, ++ { CCI_REG8(0x3e85), 0xcd }, { CCI_REG8(0x3e86), 0xcd }, ++ { CCI_REG8(0x3e87), 0xcd }, { CCI_REG8(0x3e88), 0xcd }, ++ { CCI_REG8(0x3e89), 0xcd }, { CCI_REG8(0x3e8a), 0xcd }, ++ { CCI_REG8(0x3e8b), 0xcd }, { CCI_REG8(0x3e8c), 0xcd }, ++ { CCI_REG8(0x3e8d), 0xcd }, { CCI_REG8(0x3e8e), 0xcd }, ++ { CCI_REG8(0x3e8f), 0xcd }, { CCI_REG8(0x3e90), 0xcd }, ++ { CCI_REG8(0x3e91), 0xcd }, { CCI_REG8(0x3e92), 0xcd }, ++ { CCI_REG8(0x3e93), 0xcd }, { CCI_REG8(0x3e94), 0xcd }, ++ { CCI_REG8(0x3e95), 0xcd }, { CCI_REG8(0x3e96), 0xcd }, ++ { CCI_REG8(0x3e97), 0xcd }, { CCI_REG8(0x3e98), 0xcd }, ++ { CCI_REG8(0x3e99), 0xcd }, { CCI_REG8(0x3e9a), 0xcd }, ++ { CCI_REG8(0x3e9b), 0xcd }, { CCI_REG8(0x3e9c), 0xcd }, ++ { CCI_REG8(0x3e9d), 0xcd }, { CCI_REG8(0x3e9e), 0xcd }, ++ { CCI_REG8(0x3e9f), 0xcd }, { CCI_REG8(0xfff9), 0x06 }, ++ { CCI_REG8(0xc03f), 0x01 }, { CCI_REG8(0xc03e), 0x08 }, ++ { CCI_REG8(0xc02c), 0xff }, { CCI_REG8(0xc005), 0x06 }, ++ { CCI_REG8(0xc006), 0x30 }, { CCI_REG8(0xc007), 0xc0 }, ++ { CCI_REG8(0xc027), 0x01 }, { CCI_REG8(0x30c0), 0x05 }, ++ { CCI_REG8(0x30c1), 0x9f }, { CCI_REG8(0x30c2), 0x06 }, ++ { CCI_REG8(0x30c3), 0x5f }, { CCI_REG8(0x30c4), 0x80 }, ++ { CCI_REG8(0x30c5), 0x08 }, { CCI_REG8(0x30c6), 0x39 }, ++ { CCI_REG8(0x30c7), 0x00 }, { CCI_REG8(0xc046), 0x20 }, ++ { CCI_REG8(0xc043), 0x01 }, { CCI_REG8(0xc04b), 0x01 }, ++ { CCI_REG8(0x0102), 0x01 }, { CCI_REG8(0x0100), 0x00 }, ++ { CCI_REG8(0x0102), 0x00 }, { CCI_REG8(0x3015), 0xf0 }, ++ { CCI_REG8(0x3018), 0xf0 }, { CCI_REG8(0x301c), 0xf0 }, ++ { CCI_REG8(0x301d), 0xf6 }, { CCI_REG8(0x301e), 0xf1 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_9248x6944[] = { ++ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 }, ++ { CCI_REG8(0x0307), 0x01 }, { CCI_REG8(0x4837), 0x1a }, ++ { CCI_REG8(0x4888), 0x10 }, { CCI_REG8(0x4860), 0x00 }, ++ { CCI_REG8(0x4850), 0x43 }, { CCI_REG8(0x480C), 0x92 }, ++ { CCI_REG8(0x5001), 0x21 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_8000x6000[] = { ++ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 }, ++ { CCI_REG8(0x0307), 0x01 }, { CCI_REG8(0x4837), 0x1a }, ++ { CCI_REG8(0x4888), 0x10 }, { CCI_REG8(0x4860), 0x00 }, ++ { CCI_REG8(0x4850), 0x43 }, { CCI_REG8(0x480C), 0x92 }, ++ { CCI_REG8(0x5001), 0x21 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_4624_3472[] = { ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 }, ++ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e }, ++ { CCI_REG8(0x3712), 0x50 }, { CCI_REG8(0x3822), 0x00 }, ++ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x08 }, ++ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x02 }, ++ { CCI_REG8(0x384d), 0xba }, { CCI_REG8(0x3852), 0x00 }, ++ { CCI_REG8(0x3856), 0x08 }, { CCI_REG8(0x3857), 0x08 }, ++ { CCI_REG8(0x3858), 0x10 }, { CCI_REG8(0x3859), 0x10 }, ++ { CCI_REG8(0x4016), 0x0f }, { CCI_REG8(0x4018), 0x03 }, ++ { CCI_REG8(0x4504), 0x1e }, { CCI_REG8(0x4523), 0x41 }, ++ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x12 }, ++ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4915), 0x02 }, ++ { CCI_REG8(0x4916), 0x1d }, { CCI_REG8(0x4a15), 0x02 }, ++ { CCI_REG8(0x4a16), 0x1d }, { CCI_REG8(0x3703), 0x72 }, ++ { CCI_REG8(0x3709), 0xe6 }, { CCI_REG8(0x3a60), 0x68 }, ++ { CCI_REG8(0x3a6f), 0x68 }, { CCI_REG8(0x3a5e), 0xdc }, ++ { CCI_REG8(0x3a6d), 0xdc }, { CCI_REG8(0x3721), 0xc9 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 }, ++ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 }, ++ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 }, ++ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b }, ++ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 }, ++ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b }, ++ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 }, ++ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b }, ++ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x481b), 0x35 }, ++ { CCI_REG8(0x4862), 0x25 }, { CCI_REG8(0x3400), 0x00 }, ++ { CCI_REG8(0x3421), 0x23 }, { CCI_REG8(0x3422), 0xfc }, ++ { CCI_REG8(0x3423), 0x07 }, { CCI_REG8(0x3424), 0x01 }, ++ { CCI_REG8(0x3425), 0x04 }, { CCI_REG8(0x3426), 0x50 }, ++ { CCI_REG8(0x3427), 0x55 }, { CCI_REG8(0x3428), 0x15 }, ++ { CCI_REG8(0x3429), 0x00 }, { CCI_REG8(0x3025), 0x03 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x0305), 0x98 }, ++ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 }, { CCI_REG8(0x5001), 0x21 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_3840x2160[] = { ++ { CCI_REG8(0x034a), 0x05 }, { CCI_REG8(0x034b), 0x05 }, ++ { CCI_REG8(0x3504), 0x08 }, { CCI_REG8(0x360d), 0x82 }, ++ { CCI_REG8(0x368a), 0x2e }, { CCI_REG8(0x3712), 0x50 }, ++ { CCI_REG8(0x3822), 0x00 }, { CCI_REG8(0x3827), 0x40 }, ++ { CCI_REG8(0x383d), 0x08 }, { CCI_REG8(0x383f), 0x00 }, ++ { CCI_REG8(0x384c), 0x02 }, { CCI_REG8(0x384d), 0xba }, ++ { CCI_REG8(0x3852), 0x00 }, { CCI_REG8(0x3856), 0x08 }, ++ { CCI_REG8(0x3857), 0x08 }, { CCI_REG8(0x3858), 0x10 }, ++ { CCI_REG8(0x3859), 0x10 }, { CCI_REG8(0x4016), 0x0f }, ++ { CCI_REG8(0x4018), 0x03 }, { CCI_REG8(0x4504), 0x1e }, ++ { CCI_REG8(0x4523), 0x41 }, { CCI_REG8(0x45c0), 0x01 }, ++ { CCI_REG8(0x4641), 0x12 }, { CCI_REG8(0x4643), 0x0c }, ++ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d }, ++ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d }, ++ { CCI_REG8(0x3703), 0x72 }, { CCI_REG8(0x3709), 0xe6 }, ++ { CCI_REG8(0x3a60), 0x68 }, { CCI_REG8(0x3a6f), 0x68 }, ++ { CCI_REG8(0x3a5e), 0xdc }, { CCI_REG8(0x3a6d), 0xdc }, ++ { CCI_REG8(0x3721), 0xc9 }, { CCI_REG8(0x5250), 0x06 }, ++ { CCI_REG8(0x527a), 0x00 }, { CCI_REG8(0x527b), 0x65 }, ++ { CCI_REG8(0x527c), 0x00 }, { CCI_REG8(0x527d), 0x82 }, ++ { CCI_REG8(0x5280), 0x24 }, { CCI_REG8(0x5281), 0x40 }, ++ { CCI_REG8(0x5282), 0x1b }, { CCI_REG8(0x5283), 0x40 }, ++ { CCI_REG8(0x5284), 0x24 }, { CCI_REG8(0x5285), 0x40 }, ++ { CCI_REG8(0x5286), 0x1b }, { CCI_REG8(0x5287), 0x40 }, ++ { CCI_REG8(0x5200), 0x24 }, { CCI_REG8(0x5201), 0x40 }, ++ { CCI_REG8(0x5202), 0x1b }, { CCI_REG8(0x5203), 0x40 }, ++ { CCI_REG8(0x481b), 0x35 }, { CCI_REG8(0x4862), 0x25 }, ++ { CCI_REG8(0x3400), 0x00 }, { CCI_REG8(0x3421), 0x23 }, ++ { CCI_REG8(0x3422), 0xfc }, { CCI_REG8(0x3423), 0x07 }, ++ { CCI_REG8(0x3424), 0x01 }, { CCI_REG8(0x3425), 0x04 }, ++ { CCI_REG8(0x3426), 0x50 }, { CCI_REG8(0x3427), 0x55 }, ++ { CCI_REG8(0x3428), 0x15 }, { CCI_REG8(0x3429), 0x00 }, ++ { CCI_REG8(0x3025), 0x03 }, { CCI_REG8(0x5250), 0x06 }, ++ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 }, ++ { CCI_REG8(0x0345), 0x90 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 }, { CCI_REG8(0x5001), 0x21 }, ++ { CCI_REG8(0x5000), 0x01 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_2312_1736[] = { ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 }, ++ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e }, ++ { CCI_REG8(0x3712), 0x00 }, { CCI_REG8(0x3822), 0x08 }, ++ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x04 }, ++ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x01 }, ++ { CCI_REG8(0x384d), 0x12 }, { CCI_REG8(0x3852), 0x00 }, ++ { CCI_REG8(0x3856), 0x04 }, { CCI_REG8(0x3857), 0x04 }, ++ { CCI_REG8(0x3858), 0x08 }, { CCI_REG8(0x3859), 0x08 }, ++ { CCI_REG8(0x4016), 0x07 }, { CCI_REG8(0x4018), 0x01 }, ++ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4523), 0x00 }, ++ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x24 }, ++ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4837), 0x0b }, ++ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d }, ++ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d }, ++ { CCI_REG8(0x5000), 0x55 }, { CCI_REG8(0x5001), 0x00 }, ++ { CCI_REG8(0x5002), 0x35 }, { CCI_REG8(0x5004), 0xc0 }, ++ { CCI_REG8(0x5068), 0x02 }, { CCI_REG8(0x3703), 0x6a }, ++ { CCI_REG8(0x3709), 0xa3 }, { CCI_REG8(0x3a60), 0x60 }, ++ { CCI_REG8(0x3a6f), 0x60 }, { CCI_REG8(0x3a5e), 0x99 }, ++ { CCI_REG8(0x3a6d), 0x99 }, { CCI_REG8(0x3721), 0xc1 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 }, ++ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 }, ++ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 }, ++ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b }, ++ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 }, ++ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b }, ++ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 }, ++ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b }, ++ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x3684), 0x05 }, ++ { CCI_REG8(0x481b), 0x20 }, { CCI_REG8(0x51b0), 0x38 }, ++ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x04 }, ++ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 }, ++ { CCI_REG8(0x51b9), 0x70 }, { CCI_REG8(0x51bb), 0x10 }, ++ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 }, ++ { CCI_REG8(0x51b0), 0x38 }, { CCI_REG8(0x54b0), 0x38 }, ++ { CCI_REG8(0x54b3), 0x0e }, { CCI_REG8(0x54b5), 0x04 }, ++ { CCI_REG8(0x54b6), 0x00 }, { CCI_REG8(0x54b7), 0x00 }, ++ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54bb), 0x10 }, ++ { CCI_REG8(0x54bc), 0x00 }, { CCI_REG8(0x54bd), 0x00 }, ++ { CCI_REG8(0x57b0), 0x38 }, { CCI_REG8(0x57b3), 0x0e }, ++ { CCI_REG8(0x57b5), 0x04 }, { CCI_REG8(0x57b6), 0x00 }, ++ { CCI_REG8(0x57b7), 0x00 }, { CCI_REG8(0x57b9), 0x70 }, ++ { CCI_REG8(0x57bb), 0x10 }, { CCI_REG8(0x57bc), 0x00 }, ++ { CCI_REG8(0x57bd), 0x00 }, { CCI_REG8(0x0305), 0x98 }, ++ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_1920x1080[] = { ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 }, ++ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e }, ++ { CCI_REG8(0x3712), 0x00 }, { CCI_REG8(0x3822), 0x08 }, ++ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x04 }, ++ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x01 }, ++ { CCI_REG8(0x384d), 0x12 }, { CCI_REG8(0x3852), 0x00 }, ++ { CCI_REG8(0x3856), 0x04 }, { CCI_REG8(0x3857), 0x04 }, ++ { CCI_REG8(0x3858), 0x08 }, { CCI_REG8(0x3859), 0x08 }, ++ { CCI_REG8(0x4016), 0x07 }, { CCI_REG8(0x4018), 0x01 }, ++ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4523), 0x00 }, ++ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x24 }, ++ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4837), 0x0b }, ++ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d }, ++ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d }, ++ { CCI_REG8(0x5000), 0x55 }, { CCI_REG8(0x5001), 0x00 }, ++ { CCI_REG8(0x5002), 0x35 }, { CCI_REG8(0x5004), 0xc0 }, ++ { CCI_REG8(0x5068), 0x02 }, { CCI_REG8(0x3703), 0x6a }, ++ { CCI_REG8(0x3709), 0xa3 }, { CCI_REG8(0x3a60), 0x60 }, ++ { CCI_REG8(0x3a6f), 0x60 }, { CCI_REG8(0x3a5e), 0x99 }, ++ { CCI_REG8(0x3a6d), 0x99 }, { CCI_REG8(0x3721), 0xc1 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 }, ++ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 }, ++ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 }, ++ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b }, ++ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 }, ++ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b }, ++ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 }, ++ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b }, ++ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x3684), 0x05 }, ++ { CCI_REG8(0x481b), 0x20 }, { CCI_REG8(0x51b0), 0x38 }, ++ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x04 }, ++ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 }, ++ { CCI_REG8(0x51b9), 0x70 }, { CCI_REG8(0x51bb), 0x10 }, ++ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 }, ++ { CCI_REG8(0x51b0), 0x38 }, { CCI_REG8(0x54b0), 0x38 }, ++ { CCI_REG8(0x54b3), 0x0e }, { CCI_REG8(0x54b5), 0x04 }, ++ { CCI_REG8(0x54b6), 0x00 }, { CCI_REG8(0x54b7), 0x00 }, ++ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54bb), 0x10 }, ++ { CCI_REG8(0x54bc), 0x00 }, { CCI_REG8(0x54bd), 0x00 }, ++ { CCI_REG8(0x57b0), 0x38 }, { CCI_REG8(0x57b3), 0x0e }, ++ { CCI_REG8(0x57b5), 0x04 }, { CCI_REG8(0x57b6), 0x00 }, ++ { CCI_REG8(0x57b7), 0x00 }, { CCI_REG8(0x57b9), 0x70 }, ++ { CCI_REG8(0x57bb), 0x10 }, { CCI_REG8(0x57bc), 0x00 }, ++ { CCI_REG8(0x57bd), 0x00 }, { CCI_REG8(0x0305), 0x98 }, ++ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 } ++}; ++ ++/* 456MHz MIPI link frequency with 24MHz input clock. */ ++static const struct cci_reg_sequence ov64a40_pll_config[] = { ++ { OV64A40_PLL1_PRE_DIV0, 0x88 }, ++ { OV64A40_PLL1_PRE_DIV, 0x02 }, ++ { OV64A40_PLL1_MULTIPLIER, 0x0098 }, ++ { OV64A40_PLL1_M_DIV, 0x01 }, ++ { OV64A40_PLL2_SEL_BAK_SA1, 0x00 }, ++ { OV64A40_PLL2_PRE_DIV, 0x12 }, ++ { OV64A40_PLL2_MULTIPLIER, 0x0190 }, ++ { OV64A40_PLL2_PRE_DIV0, 0xd7 }, ++ { OV64A40_PLL2_DIVSP, 0x00 }, ++ { OV64A40_PLL2_DIVDAC, 0x00 }, ++ { OV64A40_PLL2_DACPREDIV, 0x00 } ++}; ++ ++struct ov64a40_reglist { ++ unsigned int num_regs; ++ const struct cci_reg_sequence *regvals; ++}; ++ ++struct ov64a40_subsampling { ++ unsigned int x_odd_inc; ++ unsigned int x_even_inc; ++ unsigned int y_odd_inc; ++ unsigned int y_even_inc; ++ bool vbin; ++ bool hbin; ++}; ++ ++static struct ov64a40_mode { ++ unsigned int width; ++ unsigned int height; ++ struct ov64a40_timings { ++ unsigned int vts; ++ unsigned int ppl; ++ } timings_default[OV64A40_NUM_LINK_FREQ]; ++ const struct ov64a40_reglist reglist; ++ struct v4l2_rect analogue_crop; ++ struct v4l2_rect digital_crop; ++ struct ov64a40_subsampling subsampling; ++} ov64a40_modes[] = { ++ /* Full resolution */ ++ { ++ .width = 9248, ++ .height = 6944, ++ .timings_default = { ++ /* 2.6 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 7072, ++ .ppl = 4072, ++ }, ++ /* 2 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 7072, ++ .ppl = 5248, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_9248x6944), ++ .regvals = ov64a40_9248x6944, ++ }, ++ .analogue_crop = { ++ .left = 0, ++ .top = 0, ++ .width = 9279, ++ .height = 6975, ++ }, ++ .digital_crop = { ++ .left = 17, ++ .top = 16, ++ .width = 9248, ++ .height = 6944, ++ }, ++ .subsampling = { ++ .x_odd_inc = 1, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = false, ++ .hbin = false, ++ }, ++ }, ++ /* Analogue crop + digital crop */ ++ { ++ .width = 8000, ++ .height = 6000, ++ .timings_default = { ++ /* 3.0 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 6400, ++ .ppl = 3848, ++ }, ++ /* 2.5 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 6304, ++ .ppl = 4736, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_8000x6000), ++ .regvals = ov64a40_8000x6000, ++ }, ++ .analogue_crop = { ++ .left = 624, ++ .top = 472, ++ .width = 8047, ++ .height = 6031, ++ }, ++ .digital_crop = { ++ .left = 17, ++ .top = 16, ++ .width = 8000, ++ .height = 6000, ++ }, ++ .subsampling = { ++ .x_odd_inc = 1, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = false, ++ .hbin = false, ++ }, ++ }, ++ /* 2x2 downscaled */ ++ { ++ .width = 4624, ++ .height = 3472, ++ .timings_default = { ++ /* 10 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 3533, ++ .ppl = 2112, ++ }, ++ /* 7 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 3939, ++ .ppl = 2720, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_4624_3472), ++ .regvals = ov64a40_4624_3472, ++ }, ++ .analogue_crop = { ++ .left = 0, ++ .top = 0, ++ .width = 9279, ++ .height = 6975, ++ }, ++ .digital_crop = { ++ .left = 9, ++ .top = 8, ++ .width = 4624, ++ .height = 3472, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = false, ++ }, ++ }, ++ /* Analogue crop + 2x2 downscale + digital crop */ ++ { ++ .width = 3840, ++ .height = 2160, ++ .timings_default = { ++ /* 20 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 2218, ++ .ppl = 1690, ++ }, ++ /* 15 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 2270, ++ .ppl = 2202, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_3840x2160), ++ .regvals = ov64a40_3840x2160, ++ }, ++ .analogue_crop = { ++ .left = 784, ++ .top = 1312, ++ .width = 7711, ++ .height = 4351, ++ }, ++ .digital_crop = { ++ .left = 9, ++ .top = 8, ++ .width = 3840, ++ .height = 2160, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = false, ++ }, ++ }, ++ /* 4x4 downscaled */ ++ { ++ .width = 2312, ++ .height = 1736, ++ .timings_default = { ++ /* 30 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 1998, ++ .ppl = 1248, ++ }, ++ /* 25 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 1994, ++ .ppl = 1504, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_2312_1736), ++ .regvals = ov64a40_2312_1736, ++ }, ++ .analogue_crop = { ++ .left = 0, ++ .top = 0, ++ .width = 9279, ++ .height = 6975, ++ }, ++ .digital_crop = { ++ .left = 5, ++ .top = 4, ++ .width = 2312, ++ .height = 1736, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 3, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = true, ++ }, ++ }, ++ /* Analogue crop + 4x4 downscale + digital crop */ ++ { ++ .width = 1920, ++ .height = 1080, ++ .timings_default = { ++ /* 60 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 1397, ++ .ppl = 880, ++ }, ++ /* 45 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 1216, ++ .ppl = 1360, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_1920x1080), ++ .regvals = ov64a40_1920x1080, ++ }, ++ .analogue_crop = { ++ .left = 784, ++ .top = 1312, ++ .width = 7711, ++ .height = 4351, ++ }, ++ .digital_crop = { ++ .left = 7, ++ .top = 6, ++ .width = 1920, ++ .height = 1080, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 3, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = true, ++ }, ++ }, ++}; ++ ++struct ov64a40 { ++ struct device *dev; ++ ++ struct v4l2_subdev sd; ++ struct media_pad pad; ++ ++ struct regmap *cci; ++ ++ struct ov64a40_mode *mode; ++ ++ struct clk *xclk; ++ ++ struct gpio_desc *reset_gpio; ++ struct regulator_bulk_data supplies[ARRAY_SIZE(ov64a40_supply_names)]; ++ ++ s64 *link_frequencies; ++ unsigned int num_link_frequencies; ++ ++ struct v4l2_ctrl_handler ctrl_handler; ++ struct v4l2_ctrl *exposure; ++ struct v4l2_ctrl *link_freq; ++ struct v4l2_ctrl *vblank; ++ struct v4l2_ctrl *hblank; ++ struct v4l2_ctrl *vflip; ++ struct v4l2_ctrl *hflip; ++}; ++ ++static inline struct ov64a40 *sd_to_ov64a40(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct ov64a40, sd); ++} ++ ++static const struct ov64a40_timings * ++ov64a40_get_timings(struct ov64a40 *ov64a40, unsigned int link_freq_index) ++{ ++ s64 link_freq = ov64a40->link_frequencies[link_freq_index]; ++ unsigned int timings_index = link_freq == OV64A40_LINK_FREQ_360M ++ ? OV64A40_LINK_FREQ_360M_ID ++ : OV64A40_LINK_FREQ_456M_ID; ++ ++ return &ov64a40->mode->timings_default[timings_index]; ++} ++ ++static int ov64a40_program_geometry(struct ov64a40 *ov64a40) ++{ ++ struct ov64a40_mode *mode = ov64a40->mode; ++ struct v4l2_rect *anacrop = &mode->analogue_crop; ++ struct v4l2_rect *digicrop = &mode->digital_crop; ++ const struct ov64a40_timings *timings; ++ int ret = 0; ++ ++ /* Analogue crop. */ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL0, ++ anacrop->left, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL2, ++ anacrop->top, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL4, ++ anacrop->width + anacrop->left, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL6, ++ anacrop->height + anacrop->top, &ret); ++ ++ /* ISP windowing. */ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL10, ++ digicrop->left, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL12, ++ digicrop->top, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL8, ++ digicrop->width, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLA, ++ digicrop->height, &ret); ++ ++ /* Total timings. */ ++ timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLC, timings->ppl, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLE, timings->vts, &ret); ++ ++ return ret; ++} ++ ++static int ov64a40_program_subsampling(struct ov64a40 *ov64a40) ++{ ++ struct ov64a40_subsampling *subsampling = &ov64a40->mode->subsampling; ++ int ret = 0; ++ ++ /* Skipping configuration */ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL14, ++ OV64A40_SKIPPING_CONFIG(subsampling->x_odd_inc, ++ subsampling->x_even_inc), &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL15, ++ OV64A40_SKIPPING_CONFIG(subsampling->y_odd_inc, ++ subsampling->y_even_inc), &ret); ++ ++ /* Binning configuration */ ++ cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20, ++ OV64A40_TIMING_CTRL_20_VBIN, ++ subsampling->vbin ? OV64A40_TIMING_CTRL_20_VBIN : 0, ++ &ret); ++ cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21, ++ OV64A40_TIMING_CTRL_21_HBIN_CONF, ++ subsampling->hbin ? ++ OV64A40_TIMING_CTRL_21_HBIN_CONF : 0, &ret); ++ ++ return ret; ++} ++ ++static int ov64a40_start_streaming(struct ov64a40 *ov64a40, ++ struct v4l2_subdev_state *state) ++{ ++ const struct ov64a40_reglist *reglist = &ov64a40->mode->reglist; ++ const struct ov64a40_timings *timings; ++ unsigned long delay; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(ov64a40->dev); ++ if (ret < 0) ++ return ret; ++ ++ ret = cci_multi_reg_write(ov64a40->cci, ov64a40_init, ++ ARRAY_SIZE(ov64a40_init), NULL); ++ if (ret) ++ goto error_power_off; ++ ++ ret = cci_multi_reg_write(ov64a40->cci, reglist->regvals, ++ reglist->num_regs, NULL); ++ if (ret) ++ goto error_power_off; ++ ++ ret = ov64a40_program_geometry(ov64a40); ++ if (ret) ++ goto error_power_off; ++ ++ ret = ov64a40_program_subsampling(ov64a40); ++ if (ret) ++ goto error_power_off; ++ ++ ret = __v4l2_ctrl_handler_setup(&ov64a40->ctrl_handler); ++ if (ret) ++ goto error_power_off; ++ ++ ret = cci_write(ov64a40->cci, OV64A40_REG_SMIA, ++ OV64A40_REG_SMIA_STREAMING, NULL); ++ if (ret) ++ goto error_power_off; ++ ++ /* Link frequency and flips cannot change while streaming. */ ++ __v4l2_ctrl_grab(ov64a40->link_freq, true); ++ __v4l2_ctrl_grab(ov64a40->vflip, true); ++ __v4l2_ctrl_grab(ov64a40->hflip, true); ++ ++ /* delay: max(4096 xclk pulses, 150usec) + exposure time */ ++ timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val); ++ delay = DIV_ROUND_UP(4096, OV64A40_XCLK_FREQ / 1000 / 1000); ++ delay = max(delay, 150ul); ++ ++ /* The sensor has an internal x4 multiplier on the line length. */ ++ delay += DIV_ROUND_UP(timings->ppl * 4 * ov64a40->exposure->cur.val, ++ OV64A40_PIXEL_RATE / 1000 / 1000); ++ fsleep(delay); ++ ++ return 0; ++ ++error_power_off: ++ pm_runtime_mark_last_busy(ov64a40->dev); ++ pm_runtime_put_autosuspend(ov64a40->dev); ++ ++ return ret; ++} ++ ++static int ov64a40_stop_streaming(struct ov64a40 *ov64a40, ++ struct v4l2_subdev_state *state) ++{ ++ cci_update_bits(ov64a40->cci, OV64A40_REG_SMIA, BIT(0), 0, NULL); ++ pm_runtime_mark_last_busy(ov64a40->dev); ++ pm_runtime_put_autosuspend(ov64a40->dev); ++ ++ __v4l2_ctrl_grab(ov64a40->link_freq, false); ++ __v4l2_ctrl_grab(ov64a40->vflip, false); ++ __v4l2_ctrl_grab(ov64a40->hflip, false); ++ ++ return 0; ++} ++ ++static int ov64a40_set_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct v4l2_subdev_state *state; ++ int ret; ++ ++ state = v4l2_subdev_lock_and_get_active_state(sd); ++ if (enable) ++ ret = ov64a40_start_streaming(ov64a40, state); ++ else ++ ret = ov64a40_stop_streaming(ov64a40, state); ++ v4l2_subdev_unlock_state(state); ++ ++ return ret; ++} ++ ++static const struct v4l2_subdev_video_ops ov64a40_video_ops = { ++ .s_stream = ov64a40_set_stream, ++}; ++ ++static u32 ov64a40_mbus_code(struct ov64a40 *ov64a40) ++{ ++ unsigned int index = ov64a40->hflip->val << 1 | ov64a40->vflip->val; ++ ++ return ov64a40_mbus_codes[index]; ++} ++ ++static void ov64a40_update_pad_fmt(struct ov64a40 *ov64a40, ++ struct ov64a40_mode *mode, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ fmt->code = ov64a40_mbus_code(ov64a40); ++ fmt->width = mode->width; ++ fmt->height = mode->height; ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = V4L2_COLORSPACE_RAW; ++ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; ++ fmt->xfer_func = V4L2_XFER_FUNC_NONE; ++ fmt->ycbcr_enc = V4L2_YCBCR_ENC_601; ++} ++ ++static int ov64a40_init_cfg(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct v4l2_mbus_framefmt *format; ++ struct v4l2_rect *crop; ++ ++ format = v4l2_subdev_get_pad_format(sd, state, 0); ++ ov64a40_update_pad_fmt(ov64a40, &ov64a40_modes[0], format); ++ ++ crop = v4l2_subdev_get_pad_crop(sd, state, 0); ++ crop->top = OV64A40_PIXEL_ARRAY_TOP; ++ crop->left = OV64A40_PIXEL_ARRAY_LEFT; ++ crop->width = OV64A40_PIXEL_ARRAY_WIDTH; ++ crop->height = OV64A40_PIXEL_ARRAY_HEIGHT; ++ ++ return 0; ++} ++ ++static int ov64a40_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ ++ if (code->index) ++ return -EINVAL; ++ ++ code->code = ov64a40_mbus_code(ov64a40); ++ ++ return 0; ++} ++ ++static int ov64a40_enum_frame_size(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_frame_size_enum *fse) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct ov64a40_mode *mode; ++ u32 code; ++ ++ if (fse->index >= ARRAY_SIZE(ov64a40_modes)) ++ return -EINVAL; ++ ++ code = ov64a40_mbus_code(ov64a40); ++ if (fse->code != code) ++ return -EINVAL; ++ ++ mode = &ov64a40_modes[fse->index]; ++ fse->min_width = mode->width; ++ fse->max_width = mode->width; ++ fse->min_height = mode->height; ++ fse->max_height = mode->height; ++ ++ return 0; ++} ++ ++static int ov64a40_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_selection *sel) ++{ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP: ++ sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0); ++ ++ return 0; ++ ++ case V4L2_SEL_TGT_NATIVE_SIZE: ++ sel->r.top = 0; ++ sel->r.left = 0; ++ sel->r.width = OV64A40_NATIVE_WIDTH; ++ sel->r.height = OV64A40_NATIVE_HEIGHT; ++ ++ return 0; ++ ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.top = OV64A40_PIXEL_ARRAY_TOP; ++ sel->r.left = OV64A40_PIXEL_ARRAY_LEFT; ++ sel->r.width = OV64A40_PIXEL_ARRAY_WIDTH; ++ sel->r.height = OV64A40_PIXEL_ARRAY_HEIGHT; ++ ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int ov64a40_set_format(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct v4l2_mbus_framefmt *format; ++ struct ov64a40_mode *mode; ++ ++ mode = v4l2_find_nearest_size(ov64a40_modes, ++ ARRAY_SIZE(ov64a40_modes), ++ width, height, ++ fmt->format.width, fmt->format.height); ++ ++ ov64a40_update_pad_fmt(ov64a40, mode, &fmt->format); ++ ++ format = v4l2_subdev_get_pad_format(sd, sd_state, 0); ++ if (ov64a40->mode == mode && format->code == fmt->format.code) ++ return 0; ++ ++ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ++ const struct ov64a40_timings *timings; ++ int vblank_max, vblank_def; ++ int hblank_val; ++ int exp_max; ++ ++ ov64a40->mode = mode; ++ *v4l2_subdev_get_pad_crop(sd, sd_state, 0) = mode->analogue_crop; ++ ++ /* Update control limits according to the new mode. */ ++ timings = ov64a40_get_timings(ov64a40, ++ ov64a40->link_freq->cur.val); ++ vblank_max = OV64A40_VTS_MAX - mode->height; ++ vblank_def = timings->vts - mode->height; ++ __v4l2_ctrl_modify_range(ov64a40->vblank, OV64A40_VBLANK_MIN, ++ vblank_max, 1, vblank_def); ++ __v4l2_ctrl_s_ctrl(ov64a40->vblank, vblank_def); ++ ++ exp_max = timings->vts - OV64A40_EXPOSURE_MARGIN; ++ __v4l2_ctrl_modify_range(ov64a40->exposure, ++ OV64A40_EXPOSURE_MIN, exp_max, ++ 1, OV64A40_EXPOSURE_MIN); ++ ++ hblank_val = timings->ppl * 4 - mode->width; ++ __v4l2_ctrl_modify_range(ov64a40->hblank, ++ hblank_val, hblank_val, 1, hblank_val); ++ } ++ ++ *format = fmt->format; ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops ov64a40_pad_ops = { ++ .init_cfg = ov64a40_init_cfg, ++ .enum_mbus_code = ov64a40_enum_mbus_code, ++ .enum_frame_size = ov64a40_enum_frame_size, ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = ov64a40_set_format, ++ .get_selection = ov64a40_get_selection, ++}; ++ ++static const struct v4l2_subdev_core_ops ov64a40_core_ops = { ++ .subscribe_event = v4l2_ctrl_subdev_subscribe_event, ++ .unsubscribe_event = v4l2_event_subdev_unsubscribe, ++}; ++ ++static const struct v4l2_subdev_ops ov64a40_subdev_ops = { ++ .core = &ov64a40_core_ops, ++ .video = &ov64a40_video_ops, ++ .pad = &ov64a40_pad_ops, ++}; ++ ++static int ov64a40_power_on(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ int ret; ++ ++ ret = clk_prepare_enable(ov64a40->xclk); ++ if (ret) ++ return ret; ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(ov64a40_supply_names), ++ ov64a40->supplies); ++ if (ret) { ++ clk_disable_unprepare(ov64a40->xclk); ++ dev_err(dev, "Failed to enable regulators: %d\n", ret); ++ return ret; ++ } ++ ++ gpiod_set_value_cansleep(ov64a40->reset_gpio, 0); ++ ++ fsleep(5000); ++ ++ return 0; ++} ++ ++static int ov64a40_power_off(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ ++ gpiod_set_value_cansleep(ov64a40->reset_gpio, 1); ++ regulator_bulk_disable(ARRAY_SIZE(ov64a40_supply_names), ++ ov64a40->supplies); ++ clk_disable_unprepare(ov64a40->xclk); ++ ++ return 0; ++} ++ ++static int ov64a40_link_freq_config(struct ov64a40 *ov64a40, int link_freq_id) ++{ ++ s64 link_frequency; ++ int ret = 0; ++ ++ /* Default 456MHz with 24MHz input clock. */ ++ cci_multi_reg_write(ov64a40->cci, ov64a40_pll_config, ++ ARRAY_SIZE(ov64a40_pll_config), &ret); ++ ++ /* Decrease the PLL1 multiplier to obtain 360MHz mipi link frequency. */ ++ link_frequency = ov64a40->link_frequencies[link_freq_id]; ++ if (link_frequency == OV64A40_LINK_FREQ_360M) ++ cci_write(ov64a40->cci, OV64A40_PLL1_MULTIPLIER, 0x0078, &ret); ++ ++ return ret; ++} ++ ++static int ov64a40_set_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ov64a40 *ov64a40 = container_of(ctrl->handler, struct ov64a40, ++ ctrl_handler); ++ int pm_status; ++ int ret = 0; ++ ++ if (ctrl->id == V4L2_CID_VBLANK) { ++ int exp_max = ov64a40->mode->height + ctrl->val ++ - OV64A40_EXPOSURE_MARGIN; ++ int exp_val = min(ov64a40->exposure->cur.val, exp_max); ++ ++ __v4l2_ctrl_modify_range(ov64a40->exposure, ++ ov64a40->exposure->minimum, ++ exp_max, 1, exp_val); ++ } ++ ++ pm_status = pm_runtime_get_if_active(ov64a40->dev, true); ++ if (!pm_status) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_EXPOSURE: ++ ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_EXPO, ++ ctrl->val, NULL); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_GAIN, ++ ctrl->val << 1, NULL); ++ break; ++ case V4L2_CID_VBLANK: { ++ int vts = ctrl->val + ov64a40->mode->height; ++ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_LOW, vts, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_MID, ++ (vts >> 8), &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_HIGH, ++ (vts >> 16), &ret); ++ break; ++ } ++ case V4L2_CID_VFLIP: ++ ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20, ++ OV64A40_TIMING_CTRL_20_VFLIP, ++ ctrl->val << 2, ++ NULL); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21, ++ OV64A40_TIMING_CTRL_21_HFLIP, ++ ctrl->val ? 0 ++ : OV64A40_TIMING_CTRL_21_HFLIP, ++ NULL); ++ break; ++ case V4L2_CID_TEST_PATTERN: ++ ret = cci_write(ov64a40->cci, OV64A40_REG_TEST_PATTERN, ++ ov64a40_test_pattern_val[ctrl->val], NULL); ++ break; ++ case V4L2_CID_LINK_FREQ: ++ ret = ov64a40_link_freq_config(ov64a40, ctrl->val); ++ break; ++ default: ++ dev_err(ov64a40->dev, "Unhandled control: %#x\n", ctrl->id); ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (pm_status > 0) { ++ pm_runtime_mark_last_busy(ov64a40->dev); ++ pm_runtime_put_autosuspend(ov64a40->dev); ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov64a40_ctrl_ops = { ++ .s_ctrl = ov64a40_set_ctrl, ++}; ++ ++static int ov64a40_init_controls(struct ov64a40 *ov64a40) ++{ ++ int exp_max, hblank_val, vblank_max, vblank_def; ++ struct v4l2_ctrl_handler *hdlr = &ov64a40->ctrl_handler; ++ struct v4l2_fwnode_device_properties props; ++ const struct ov64a40_timings *timings; ++ int ret; ++ ++ ret = v4l2_ctrl_handler_init(hdlr, 11); ++ if (ret) ++ return ret; ++ ++ v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, V4L2_CID_PIXEL_RATE, ++ OV64A40_PIXEL_RATE, OV64A40_PIXEL_RATE, 1, ++ OV64A40_PIXEL_RATE); ++ ++ ov64a40->link_freq = ++ v4l2_ctrl_new_int_menu(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ ov64a40->num_link_frequencies - 1, ++ 0, ov64a40->link_frequencies); ++ ++ v4l2_ctrl_new_std_menu_items(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_TEST_PATTERN, ++ ARRAY_SIZE(ov64a40_test_pattern_menu) - 1, ++ 0, 0, ov64a40_test_pattern_menu); ++ ++ timings = ov64a40_get_timings(ov64a40, 0); ++ exp_max = timings->vts - OV64A40_EXPOSURE_MARGIN; ++ ov64a40->exposure = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_EXPOSURE, ++ OV64A40_EXPOSURE_MIN, exp_max, 1, ++ OV64A40_EXPOSURE_MIN); ++ ++ hblank_val = timings->ppl * 4 - ov64a40->mode->width; ++ ov64a40->hblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_HBLANK, hblank_val, ++ hblank_val, 1, hblank_val); ++ if (ov64a40->hblank) ++ ov64a40->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ++ vblank_def = timings->vts - ov64a40->mode->height; ++ vblank_max = OV64A40_VTS_MAX - ov64a40->mode->height; ++ ov64a40->vblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_VBLANK, OV64A40_VBLANK_MIN, ++ vblank_max, 1, vblank_def); ++ ++ v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, ++ OV64A40_ANA_GAIN_MIN, OV64A40_ANA_GAIN_MAX, 1, ++ OV64A40_ANA_GAIN_DEFAULT); ++ ++ ov64a40->hflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ if (ov64a40->hflip) ++ ov64a40->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; ++ ++ ov64a40->vflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ if (ov64a40->vflip) ++ ov64a40->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; ++ ++ if (hdlr->error) { ++ ret = hdlr->error; ++ dev_err(ov64a40->dev, "control init failed: %d\n", ret); ++ goto error_free_hdlr; ++ } ++ ++ ret = v4l2_fwnode_device_parse(ov64a40->dev, &props); ++ if (ret) ++ goto error_free_hdlr; ++ ++ ret = v4l2_ctrl_new_fwnode_properties(hdlr, &ov64a40_ctrl_ops, ++ &props); ++ if (ret) ++ goto error_free_hdlr; ++ ++ ov64a40->sd.ctrl_handler = hdlr; ++ ++ return 0; ++ ++error_free_hdlr: ++ v4l2_ctrl_handler_free(hdlr); ++ return ret; ++} ++ ++static int ov64a40_identify(struct ov64a40 *ov64a40) ++{ ++ int ret; ++ u64 id; ++ ++ ret = cci_read(ov64a40->cci, OV64A40_REG_CHIP_ID, &id, NULL); ++ if (ret) { ++ dev_err(ov64a40->dev, "Failed to read chip id: %d\n", ret); ++ return ret; ++ } ++ ++ if (id != OV64A40_CHIP_ID) { ++ dev_err(ov64a40->dev, "chip id mismatch: %#llx\n", id); ++ return -ENODEV; ++ } ++ ++ dev_dbg(ov64a40->dev, "OV64A40 chip identified: %#llx\n", id); ++ ++ return 0; ++} ++ ++static int ov64a40_parse_dt(struct ov64a40 *ov64a40) ++{ ++ struct v4l2_fwnode_endpoint v4l2_fwnode = { ++ .bus_type = V4L2_MBUS_CSI2_DPHY ++ }; ++ struct fwnode_handle *endpoint; ++ int ret = -EINVAL; ++ unsigned int i; ++ ++ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(ov64a40->dev), ++ NULL); ++ if (!endpoint) { ++ dev_err(ov64a40->dev, "Failed to find endpoint\n"); ++ return -EINVAL; ++ } ++ ++ if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &v4l2_fwnode)) { ++ dev_err(ov64a40->dev, "Failed to parse endpoint\n"); ++ goto error_put_fwnode; ++ ++ } ++ ++ if (v4l2_fwnode.bus.mipi_csi2.num_data_lanes != 2) { ++ dev_err(ov64a40->dev, "Unsupported number of data lanes: %u\n", ++ v4l2_fwnode.bus.mipi_csi2.num_data_lanes); ++ goto error_free_fwnode; ++ } ++ ++ if (!v4l2_fwnode.nr_of_link_frequencies) { ++ dev_warn(ov64a40->dev, "no link frequencies defined\n"); ++ goto error_free_fwnode; ++ } ++ ++ if (v4l2_fwnode.nr_of_link_frequencies > 2) { ++ dev_warn(ov64a40->dev, ++ "Unsupported number of link frequencies\n"); ++ goto error_free_fwnode; ++ } ++ ++ ov64a40->link_frequencies = ++ devm_kcalloc(ov64a40->dev, v4l2_fwnode.nr_of_link_frequencies, ++ sizeof(v4l2_fwnode.link_frequencies[0]), ++ GFP_KERNEL); ++ if (!ov64a40->link_frequencies) { ++ ret = -ENOMEM; ++ goto error_free_fwnode; ++ } ++ ov64a40->num_link_frequencies = v4l2_fwnode.nr_of_link_frequencies; ++ ++ for (i = 0; i < v4l2_fwnode.nr_of_link_frequencies; ++i) { ++ if (v4l2_fwnode.link_frequencies[i] != OV64A40_LINK_FREQ_360M && ++ v4l2_fwnode.link_frequencies[i] != OV64A40_LINK_FREQ_456M) { ++ dev_err(ov64a40->dev, ++ "Unsupported link frequency %lld\n", ++ v4l2_fwnode.link_frequencies[i]); ++ goto error_free_fwnode; ++ } ++ ++ ov64a40->link_frequencies[i] = v4l2_fwnode.link_frequencies[i]; ++ } ++ ++ v4l2_fwnode_endpoint_free(&v4l2_fwnode); ++ ++ /* Register the subdev on the endpoint, so don't put it yet. */ ++ ov64a40->sd.fwnode = endpoint; ++ ++ return 0; ++ ++error_free_fwnode: ++ v4l2_fwnode_endpoint_free(&v4l2_fwnode); ++error_put_fwnode: ++ fwnode_handle_put(endpoint); ++ return ret; ++} ++ ++static int ov64a40_get_regulators(struct ov64a40 *ov64a40) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&ov64a40->sd); ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ov64a40_supply_names); i++) ++ ov64a40->supplies[i].supply = ov64a40_supply_names[i]; ++ ++ return devm_regulator_bulk_get(&client->dev, ++ ARRAY_SIZE(ov64a40_supply_names), ++ ov64a40->supplies); ++} ++ ++static int ov64a40_probe(struct i2c_client *client) ++{ ++ struct ov64a40 *ov64a40; ++ u32 xclk_freq; ++ int ret; ++ ++ ov64a40 = devm_kzalloc(&client->dev, sizeof(*ov64a40), GFP_KERNEL); ++ if (!ov64a40) ++ return -ENOMEM; ++ ++ ov64a40->dev = &client->dev; ++ v4l2_i2c_subdev_init(&ov64a40->sd, client, &ov64a40_subdev_ops); ++ ++ ov64a40->cci = devm_cci_regmap_init_i2c(client, 16); ++ if (IS_ERR(ov64a40->cci)) { ++ dev_err(&client->dev, "Failed to initialize CCI\n"); ++ return PTR_ERR(ov64a40->cci); ++ } ++ ++ ov64a40->xclk = devm_clk_get(&client->dev, NULL); ++ if (!ov64a40->xclk) ++ return dev_err_probe(&client->dev, PTR_ERR(ov64a40->xclk), ++ "Failed to get clock\n"); ++ ++ xclk_freq = clk_get_rate(ov64a40->xclk); ++ if (xclk_freq != OV64A40_XCLK_FREQ) { ++ dev_err(&client->dev, "Unsupported xclk frequency %u\n", ++ xclk_freq); ++ return -EINVAL; ++ } ++ ++ ret = ov64a40_get_regulators(ov64a40); ++ if (ret) ++ return ret; ++ ++ ov64a40->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(ov64a40->reset_gpio)) ++ return dev_err_probe(&client->dev, PTR_ERR(ov64a40->reset_gpio), ++ "Failed to get reset gpio\n"); ++ ++ ret = ov64a40_parse_dt(ov64a40); ++ if (ret) ++ return ret; ++ ++ ret = ov64a40_power_on(&client->dev); ++ if (ret) ++ goto error_put_fwnode; ++ ++ ret = ov64a40_identify(ov64a40); ++ if (ret) ++ goto error_poweroff; ++ ++ ov64a40->mode = &ov64a40_modes[0]; ++ ++ pm_runtime_set_active(&client->dev); ++ pm_runtime_get_noresume(&client->dev); ++ pm_runtime_enable(&client->dev); ++ pm_runtime_set_autosuspend_delay(&client->dev, 1000); ++ pm_runtime_use_autosuspend(&client->dev); ++ ++ ret = ov64a40_init_controls(ov64a40); ++ if (ret) ++ goto error_poweroff; ++ ++ /* Initialize subdev */ ++ ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE ++ | V4L2_SUBDEV_FL_HAS_EVENTS; ++ ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ++ ++ ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE; ++ ret = media_entity_pads_init(&ov64a40->sd.entity, 1, &ov64a40->pad); ++ if (ret) { ++ dev_err(&client->dev, "failed to init entity pads: %d\n", ret); ++ goto error_handler_free; ++ } ++ ++ ov64a40->sd.state_lock = ov64a40->ctrl_handler.lock; ++ ret = v4l2_subdev_init_finalize(&ov64a40->sd); ++ if (ret < 0) { ++ dev_err(&client->dev, "subdev init error: %d\n", ret); ++ goto error_media_entity; ++ } ++ ++ ret = v4l2_async_register_subdev_sensor(&ov64a40->sd); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "failed to register sensor sub-device: %d\n", ret); ++ goto error_subdev_cleanup; ++ } ++ ++ pm_runtime_mark_last_busy(&client->dev); ++ pm_runtime_put_autosuspend(&client->dev); ++ ++ return 0; ++ ++error_subdev_cleanup: ++ v4l2_subdev_cleanup(&ov64a40->sd); ++error_media_entity: ++ media_entity_cleanup(&ov64a40->sd.entity); ++error_handler_free: ++ v4l2_ctrl_handler_free(ov64a40->sd.ctrl_handler); ++error_poweroff: ++ ov64a40_power_off(&client->dev); ++ pm_runtime_set_suspended(&client->dev); ++error_put_fwnode: ++ fwnode_handle_put(ov64a40->sd.fwnode); ++ ++ return ret; ++} ++ ++static void ov64a40_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ ++ v4l2_async_unregister_subdev(sd); ++ fwnode_handle_put(ov64a40->sd.fwnode); ++ v4l2_subdev_cleanup(sd); ++ media_entity_cleanup(&sd->entity); ++ v4l2_ctrl_handler_free(sd->ctrl_handler); ++ ++ pm_runtime_disable(&client->dev); ++ if (!pm_runtime_status_suspended(&client->dev)) ++ ov64a40_power_off(&client->dev); ++ pm_runtime_set_suspended(&client->dev); ++} ++ ++static const struct of_device_id ov64a40_of_ids[] = { ++ { .compatible = "ovti,ov64a40" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, ov64a40_of_ids); ++ ++static const struct dev_pm_ops ov64a40_pm_ops = { ++ SET_RUNTIME_PM_OPS(ov64a40_power_off, ov64a40_power_on, NULL) ++}; ++ ++static struct i2c_driver ov64a40_i2c_driver = { ++ .driver = { ++ .name = "ov64a40", ++ .of_match_table = ov64a40_of_ids, ++ .pm = &ov64a40_pm_ops, ++ }, ++ .probe_new = ov64a40_probe, ++ .remove = ov64a40_remove, ++}; ++ ++module_i2c_driver(ov64a40_i2c_driver); ++ ++MODULE_AUTHOR("Jacopo Mondi "); ++MODULE_DESCRIPTION("OmniVision OV64A40 sensor driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-1196-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch b/target/linux/bcm27xx/patches-6.1/950-1196-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch new file mode 100644 index 0000000000..a50617ee56 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1196-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch @@ -0,0 +1,368 @@ +From 97ec6aeb265df0bfe7193f00c249b38873fb0fb7 Mon Sep 17 00:00:00 2001 +From: Kieran Bingham +Date: Wed, 13 Sep 2023 17:53:54 +0100 +Subject: [PATCH] media: i2c: Add ROHM BU64754 Camera Autofocus Actuator + +Add support for the ROHM BU64754 Motor Driver for Camera Autofocus. A +V4L2 Subdevice is registered and provides a single +V4L2_CID_FOCUS_ABSOLUTE control. + +Signed-off-by: Kieran Bingham +Signed-off-by: Jacopo Mondi +--- + drivers/media/i2c/Kconfig | 13 ++ + drivers/media/i2c/Makefile | 1 + + drivers/media/i2c/bu64754.c | 315 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 329 insertions(+) + create mode 100644 drivers/media/i2c/bu64754.c + +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -917,6 +917,19 @@ config VIDEO_AK7375 + capability. This is designed for linear control of + voice coil motors, controlled via I2C serial interface. + ++config VIDEO_BU64754 ++ tristate "BU64754 Motor Driver for Camera Autofocus" ++ depends on I2C && VIDEO_DEV ++ select MEDIA_CONTROLLER ++ select VIDEO_V4L2_SUBDEV_API ++ select V4L2_ASYNC ++ select V4L2_CCI_I2C ++ help ++ This is a driver for the BU64754 Motor Driver for Camera ++ Autofocus. The BU64754GWZ is an actuator driver IC which ++ can be controlled the actuator position precisely using ++ with internal Hall Sensor. ++ + config VIDEO_DW9714 + tristate "DW9714 lens voice coil support" + depends on I2C && VIDEO_DEV +--- a/drivers/media/i2c/Makefile ++++ b/drivers/media/i2c/Makefile +@@ -26,6 +26,7 @@ obj-$(CONFIG_VIDEO_ARDUCAM_PIVARIETY) += + obj-$(CONFIG_VIDEO_BT819) += bt819.o + obj-$(CONFIG_VIDEO_BT856) += bt856.o + obj-$(CONFIG_VIDEO_BT866) += bt866.o ++obj-$(CONFIG_VIDEO_BU64754) += bu64754.o + obj-$(CONFIG_VIDEO_CCS) += ccs/ + obj-$(CONFIG_VIDEO_CCS_PLL) += ccs-pll.o + obj-$(CONFIG_VIDEO_CS3308) += cs3308.o +--- /dev/null ++++ b/drivers/media/i2c/bu64754.c +@@ -0,0 +1,315 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * The BU64754GWZ is an actuator driver IC which can control the ++ * actuator position precisely using an internal Hall Sensor. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define BU64754_REG_ACTIVE CCI_REG16(0x07) ++#define BU64754_ACTIVE_MODE 0x8080 ++ ++#define BU64754_REG_SERVE CCI_REG16(0xd9) ++#define BU64754_SERVE_ON 0x0404 ++ ++#define BU64754_REG_POSITION CCI_REG16(0x45) ++#define BU64753_POSITION_MAX 1023 /* 0x3ff */ ++#define BU64753_POSITION_STEPS 1 ++ ++#define BU64754_POWER_ON_DELAY 800 /* uS : t1, t3 */ ++ ++struct bu64754 { ++ struct device *dev; ++ ++ struct v4l2_ctrl_handler ctrls_vcm; ++ struct v4l2_subdev sd; ++ struct regmap *cci; ++ ++ u16 current_val; ++ struct regulator *vdd; ++ struct notifier_block notifier; ++}; ++ ++static inline struct bu64754 *sd_to_bu64754(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct bu64754, sd); ++} ++ ++static int bu64754_set(struct bu64754 *bu64754, u16 position) ++{ ++ int ret; ++ ++ position &= 0x3ff; /* BU64753_POSITION_MAX */ ++ ret = cci_write(bu64754->cci, BU64754_REG_POSITION, position, NULL); ++ if (ret) { ++ dev_err(bu64754->dev, "Set position failed ret=%d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bu64754_active(struct bu64754 *bu64754) ++{ ++ int ret; ++ ++ /* Power on */ ++ ret = cci_write(bu64754->cci, BU64754_REG_ACTIVE, BU64754_ACTIVE_MODE, NULL); ++ if (ret < 0) { ++ dev_err(bu64754->dev, "Failed to set active mode ret = %d\n", ++ ret); ++ return ret; ++ } ++ ++ /* Serve on */ ++ ret = cci_write(bu64754->cci, BU64754_REG_SERVE, BU64754_SERVE_ON, NULL); ++ if (ret < 0) { ++ dev_err(bu64754->dev, "Failed to enable serve ret = %d\n", ++ ret); ++ return ret; ++ } ++ ++ return bu64754_set(bu64754, bu64754->current_val); ++} ++ ++static int bu64754_standby(struct bu64754 *bu64754) ++{ ++ int ret; ++ ++ ret = cci_write(bu64754->cci, BU64754_REG_ACTIVE, 0, NULL); ++ if (ret < 0) ++ dev_err(bu64754->dev, "Failed to enter standby mode ret = %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int bu64754_regulator_event(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ struct bu64754 *bu64754 = container_of(nb, struct bu64754, notifier); ++ ++ if (action & REGULATOR_EVENT_ENABLE) { ++ /* ++ * Initialisation delay between VDD low->high and availability ++ * i2c operation. ++ */ ++ usleep_range(BU64754_POWER_ON_DELAY, ++ BU64754_POWER_ON_DELAY + 100); ++ ++ bu64754_active(bu64754); ++ } else if (action & REGULATOR_EVENT_PRE_DISABLE) { ++ bu64754_standby(bu64754); ++ } ++ ++ return 0; ++} ++ ++static int bu64754_set_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct bu64754 *bu64754 = container_of(ctrl->handler, ++ struct bu64754, ctrls_vcm); ++ ++ if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { ++ bu64754->current_val = ctrl->val; ++ return bu64754_set(bu64754, ctrl->val); ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct v4l2_ctrl_ops bu64754_vcm_ctrl_ops = { ++ .s_ctrl = bu64754_set_ctrl, ++}; ++ ++static int bu64754_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ++{ ++ return pm_runtime_resume_and_get(sd->dev); ++} ++ ++static int bu64754_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ++{ ++ pm_runtime_put(sd->dev); ++ return 0; ++} ++ ++static const struct v4l2_subdev_internal_ops bu64754_int_ops = { ++ .open = bu64754_open, ++ .close = bu64754_close, ++}; ++ ++static const struct v4l2_subdev_ops bu64754_ops = { }; ++ ++static void bu64754_subdev_cleanup(struct bu64754 *bu64754) ++{ ++ v4l2_async_unregister_subdev(&bu64754->sd); ++ v4l2_ctrl_handler_free(&bu64754->ctrls_vcm); ++ media_entity_cleanup(&bu64754->sd.entity); ++} ++ ++static int bu64754_init_controls(struct bu64754 *bu64754) ++{ ++ struct v4l2_ctrl_handler *hdl = &bu64754->ctrls_vcm; ++ const struct v4l2_ctrl_ops *ops = &bu64754_vcm_ctrl_ops; ++ ++ v4l2_ctrl_handler_init(hdl, 1); ++ ++ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, ++ 0, BU64753_POSITION_MAX, BU64753_POSITION_STEPS, ++ 0); ++ ++ bu64754->current_val = 0; ++ ++ bu64754->sd.ctrl_handler = hdl; ++ if (hdl->error) { ++ dev_err(bu64754->dev, "%s fail error: 0x%x\n", ++ __func__, hdl->error); ++ return hdl->error; ++ } ++ ++ return 0; ++} ++ ++static int bu64754_probe(struct i2c_client *client) ++{ ++ struct bu64754 *bu64754; ++ int ret; ++ ++ bu64754 = devm_kzalloc(&client->dev, sizeof(*bu64754), GFP_KERNEL); ++ if (!bu64754) ++ return -ENOMEM; ++ ++ bu64754->dev = &client->dev; ++ ++ bu64754->cci = devm_cci_regmap_init_i2c(client, 8); ++ if (IS_ERR(bu64754->cci)) { ++ dev_err(bu64754->dev, "Failed to initialize CCI\n"); ++ return PTR_ERR(bu64754->cci); ++ } ++ ++ bu64754->vdd = devm_regulator_get_optional(&client->dev, "vdd"); ++ if (IS_ERR(bu64754->vdd)) { ++ if (PTR_ERR(bu64754->vdd) != -ENODEV) ++ return PTR_ERR(bu64754->vdd); ++ ++ bu64754->vdd = NULL; ++ } else { ++ bu64754->notifier.notifier_call = bu64754_regulator_event; ++ ++ ret = regulator_register_notifier(bu64754->vdd, ++ &bu64754->notifier); ++ if (ret) { ++ dev_err(bu64754->dev, ++ "could not register regulator notifier\n"); ++ return ret; ++ } ++ } ++ ++ v4l2_i2c_subdev_init(&bu64754->sd, client, &bu64754_ops); ++ bu64754->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ bu64754->sd.internal_ops = &bu64754_int_ops; ++ bu64754->sd.entity.function = MEDIA_ENT_F_LENS; ++ ++ ret = bu64754_init_controls(bu64754); ++ if (ret) ++ goto err_cleanup; ++ ++ ret = media_entity_pads_init(&bu64754->sd.entity, 0, NULL); ++ if (ret < 0) ++ goto err_cleanup; ++ ++ bu64754->sd.entity.function = MEDIA_ENT_F_LENS; ++ ++ ret = v4l2_async_register_subdev(&bu64754->sd); ++ if (ret < 0) ++ goto err_cleanup; ++ ++ if (!bu64754->vdd) ++ pm_runtime_set_active(&client->dev); ++ ++ pm_runtime_enable(&client->dev); ++ pm_runtime_idle(&client->dev); ++ ++ return 0; ++ ++err_cleanup: ++ v4l2_ctrl_handler_free(&bu64754->ctrls_vcm); ++ media_entity_cleanup(&bu64754->sd.entity); ++ ++ return ret; ++} ++ ++static void bu64754_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct bu64754 *bu64754 = sd_to_bu64754(sd); ++ ++ if (bu64754->vdd) ++ regulator_unregister_notifier(bu64754->vdd, ++ &bu64754->notifier); ++ ++ pm_runtime_disable(&client->dev); ++ ++ bu64754_subdev_cleanup(bu64754); ++} ++ ++static int __maybe_unused bu64754_vcm_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct bu64754 *bu64754 = sd_to_bu64754(sd); ++ ++ if (bu64754->vdd) ++ return regulator_disable(bu64754->vdd); ++ ++ return bu64754_standby(bu64754); ++} ++ ++static int __maybe_unused bu64754_vcm_resume(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct bu64754 *bu64754 = sd_to_bu64754(sd); ++ ++ if (bu64754->vdd) ++ return regulator_enable(bu64754->vdd); ++ ++ return bu64754_active(bu64754); ++} ++ ++static const struct of_device_id bu64754_of_table[] = { ++ { .compatible = "rohm,bu64754", }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, bu64754_of_table); ++ ++static const struct dev_pm_ops bu64754_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(bu64754_vcm_suspend, bu64754_vcm_resume) ++ SET_RUNTIME_PM_OPS(bu64754_vcm_suspend, bu64754_vcm_resume, NULL) ++}; ++ ++static struct i2c_driver bu64754_i2c_driver = { ++ .driver = { ++ .name = "bu64754", ++ .pm = &bu64754_pm_ops, ++ .of_match_table = bu64754_of_table, ++ }, ++ .probe_new = bu64754_probe, ++ .remove = bu64754_remove, ++}; ++ ++module_i2c_driver(bu64754_i2c_driver); ++ ++MODULE_AUTHOR("Kieran Bingham"); ++MODULE_DESCRIPTION("BU64754 VCM driver"); ++MODULE_LICENSE("GPL"); ++ diff --git a/target/linux/bcm27xx/patches-6.1/950-1197-overlays-Add-overlay-for-the-OV64A40-Arducam-Camera-.patch b/target/linux/bcm27xx/patches-6.1/950-1197-overlays-Add-overlay-for-the-OV64A40-Arducam-Camera-.patch new file mode 100644 index 0000000000..d3ee0dc68e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1197-overlays-Add-overlay-for-the-OV64A40-Arducam-Camera-.patch @@ -0,0 +1,426 @@ +From 7f67a45ee7c008c3d8e45fde6fa9c4287fb3bc9e Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 20 Jul 2023 13:18:34 +0200 +Subject: [PATCH] overlays: Add overlay for the OV64A40 Arducam Camera Module + +Arducam have integrated an Omnivision OV64A40 with a ROHM BU64754 VCM +with a Raspberry Pi compatible cable pinout. + +Provide an overlay to support the module. + +Also add support to the camera mux overlays. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Kieran Bingham +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 25 +++++ + .../dts/overlays/camera-mux-2port-overlay.dts | 32 +++++++ + .../dts/overlays/camera-mux-4port-overlay.dts | 64 +++++++++++++ + .../arm/boot/dts/overlays/ov64a40-overlay.dts | 91 +++++++++++++++++++ + arch/arm/boot/dts/overlays/ov64a40.dtsi | 34 +++++++ + 6 files changed, 247 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/ov64a40-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/ov64a40.dtsi + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -175,6 +175,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + mz61581.dtbo \ + ov2311.dtbo \ + ov5647.dtbo \ ++ ov64a40.dtbo \ + ov7251.dtbo \ + ov9281.dtbo \ + papirus.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -817,6 +817,7 @@ Params: cam0-arducam-64mp Select A + cam0-imx708 Select IMX708 for camera on port 0 + cam0-ov2311 Select OV2311 for camera on port 0 + cam0-ov5647 Select OV5647 for camera on port 0 ++ cam0-ov64a40 Select OV64A40 for camera on port 0 + cam0-ov7251 Select OV7251 for camera on port 0 + cam0-ov9281 Select OV9281 for camera on port 0 + cam0-imx290-clk-freq Set clock frequency for an IMX290 on port 0 +@@ -829,6 +830,7 @@ Params: cam0-arducam-64mp Select A + cam1-imx708 Select IMX708 for camera on port 1 + cam1-ov2311 Select OV2311 for camera on port 1 + cam1-ov5647 Select OV5647 for camera on port 1 ++ cam1-ov64a40 Select OV64A40 for camera on port 1 + cam1-ov7251 Select OV7251 for camera on port 1 + cam1-ov9281 Select OV9281 for camera on port 1 + cam1-imx290-clk-freq Set clock frequency for an IMX290 on port 1 +@@ -850,6 +852,7 @@ Params: cam0-arducam-64mp Select A + cam0-imx708 Select IMX708 for camera on port 0 + cam0-ov2311 Select OV2311 for camera on port 0 + cam0-ov5647 Select OV5647 for camera on port 0 ++ cam0-ov64a40 Select OV64A40 for camera on port 0 + cam0-ov7251 Select OV7251 for camera on port 0 + cam0-ov9281 Select OV9281 for camera on port 0 + cam0-imx290-clk-freq Set clock frequency for an IMX290 on port 0 +@@ -862,6 +865,7 @@ Params: cam0-arducam-64mp Select A + cam1-imx708 Select IMX708 for camera on port 1 + cam1-ov2311 Select OV2311 for camera on port 1 + cam1-ov5647 Select OV5647 for camera on port 1 ++ cam1-ov64a40 Select OV64A40 for camera on port 1 + cam1-ov7251 Select OV7251 for camera on port 1 + cam1-ov9281 Select OV9281 for camera on port 1 + cam1-imx290-clk-freq Set clock frequency for an IMX290 on port 1 +@@ -874,6 +878,7 @@ Params: cam0-arducam-64mp Select A + cam2-imx708 Select IMX708 for camera on port 2 + cam2-ov2311 Select OV2311 for camera on port 2 + cam2-ov5647 Select OV5647 for camera on port 2 ++ cam2-ov64a40 Select OV64A40 for camera on port 2 + cam2-ov7251 Select OV7251 for camera on port 2 + cam2-ov9281 Select OV9281 for camera on port 2 + cam2-imx290-clk-freq Set clock frequency for an IMX290 on port 2 +@@ -886,6 +891,7 @@ Params: cam0-arducam-64mp Select A + cam3-imx708 Select IMX708 for camera on port 3 + cam3-ov2311 Select OV2311 for camera on port 3 + cam3-ov5647 Select OV5647 for camera on port 3 ++ cam3-ov64a40 Select OV64A40 for camera on port 3 + cam3-ov7251 Select OV7251 for camera on port 3 + cam3-ov9281 Select OV9281 for camera on port 3 + cam3-imx290-clk-freq Set clock frequency for an IMX290 on port 3 +@@ -3222,6 +3228,25 @@ Params: rotation Mounting + vcm Configure a VCM focus drive on the sensor. + + ++Name: ov64a40 ++Info: Arducam OV64A40 camera module. ++ Uses Unicam 1, which is the standard camera connector on most Pi ++ variants. ++Load: dtoverlay=ov64a40,= ++Params: rotation Mounting rotation of the camera sensor (0 or ++ 180, default 0) ++ orientation Sensor orientation (0 = front, 1 = rear, ++ 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). ++ vcm Select lens driver state. Default is enabled, ++ but vcm=off will disable. ++ link-frequency Allowable link frequency values to use in Hz: ++ 456000000 (default), 360000000 ++ ++ + Name: ov7251 + Info: Omnivision OV7251 camera module. + Uses Unicam 1, which is the standard camera connector on most Pi +--- a/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts +@@ -189,6 +189,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_0 ++ #define cam_endpoint ov64a40_0_ep ++ #define vcm_node ov64a40_0_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@1 { +@@ -289,6 +299,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_1 ++ #define cam_endpoint ov64a40_1_ep ++ #define vcm_node ov64a40_1_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + }; + }; +@@ -450,6 +470,12 @@ + cam0-ov2311 = <&mux_in0>, "remote-endpoint:0=",<&ov2311_0_ep>, + <&ov2311_0_ep>, "remote-endpoint:0=",<&mux_in0>, + <&ov2311_0>, "status=okay"; ++ cam0-ov64a40 = <&mux_in0>, "remote-endpoint:0=",<&ov64a40_0_ep>, ++ <&ov64a40_0_ep>, "remote-endpoint:0=",<&mux_in0>, ++ <&mux_in0>, "clock-noncontinuous?", ++ <&ov64a40_0>, "status=okay", ++ <&ov64a40_0_vcm>, "status=okay", ++ <&ov64a40_0>,"lens-focus:0=", <&ov64a40_0_vcm>; + + cam1-arducam-64mp = <&mux_in1>, "remote-endpoint:0=",<&arducam_64mp_1_ep>, + <&arducam_64mp_1_ep>, "remote-endpoint:0=",<&mux_in1>, +@@ -496,6 +522,12 @@ + cam1-ov2311 = <&mux_in1>, "remote-endpoint:0=",<&ov2311_1_ep>, + <&ov2311_1_ep>, "remote-endpoint:0=",<&mux_in1>, + <&ov2311_1>, "status=okay"; ++ cam1-ov64a40 = <&mux_in1>, "remote-endpoint:0=",<&ov64a40_1_ep>, ++ <&ov64a40_1_ep>, "remote-endpoint:0=",<&mux_in1>, ++ <&mux_in1>, "clock-noncontinuous?", ++ <&ov64a40_1>, "status=okay", ++ <&ov64a40_1_vcm>, "status=okay", ++ <&ov64a40_1>,"lens-focus:0=", <&ov64a40_1_vcm>; + + cam0-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_0>,"clock-frequency:0"; +--- a/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts +@@ -247,6 +247,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_0 ++ #define cam_endpoint ov64a40_0_ep ++ #define vcm_node ov64a40_0_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@1 { +@@ -347,6 +357,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_1 ++ #define cam_endpoint ov64a40_1_ep ++ #define vcm_node ov64a40_1_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@2 { +@@ -447,6 +467,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_2 ++ #define cam_endpoint ov64a40_2_ep ++ #define vcm_node ov64a40_2_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@3 { +@@ -547,6 +577,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_3 ++ #define cam_endpoint ov64a40_3_ep ++ #define vcm_node ov64a40_3_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + }; + }; +@@ -725,6 +765,12 @@ + cam0-ov2311 = <&mux_in0>, "remote-endpoint:0=",<&ov2311_0_ep>, + <&ov2311_0_ep>, "remote-endpoint:0=",<&mux_in0>, + <&ov2311_0>, "status=okay"; ++ cam0-ov64a40 = <&mux_in0>, "remote-endpoint:0=",<&ov64a40_0_ep>, ++ <&ov64a40_0_ep>, "remote-endpoint:0=",<&mux_in0>, ++ <&mux_in0>, "clock-noncontinuous?", ++ <&ov64a40_0>, "status=okay", ++ <&ov64a40_0_vcm>, "status=okay", ++ <&ov64a40_0>,"lens-focus:0=", <&ov64a40_0_vcm>; + + cam1-arducam-64mp = <&mux_in1>, "remote-endpoint:0=",<&arducam_64mp_1_ep>, + <&arducam_64mp_1_ep>, "remote-endpoint:0=",<&mux_in1>, +@@ -771,6 +817,12 @@ + cam1-ov2311 = <&mux_in1>, "remote-endpoint:0=",<&ov2311_1_ep>, + <&ov2311_1_ep>, "remote-endpoint:0=",<&mux_in1>, + <&ov2311_1>, "status=okay"; ++ cam1-ov64a40 = <&mux_in1>, "remote-endpoint:0=",<&ov64a40_1_ep>, ++ <&ov64a40_1_ep>, "remote-endpoint:0=",<&mux_in1>, ++ <&mux_in1>, "clock-noncontinuous?", ++ <&ov64a40_1>, "status=okay", ++ <&ov64a40_1_vcm>, "status=okay", ++ <&ov64a40_1>,"lens-focus:0=", <&ov64a40_1_vcm>; + + cam2-arducam-64mp = <&mux_in2>, "remote-endpoint:0=",<&arducam_64mp_2_ep>, + <&arducam_64mp_2_ep>, "remote-endpoint:0=",<&mux_in2>, +@@ -817,6 +869,12 @@ + cam2-ov2311 = <&mux_in2>, "remote-endpoint:0=",<&ov2311_2_ep>, + <&ov2311_2_ep>, "remote-endpoint:0=",<&mux_in2>, + <&ov2311_2>, "status=okay"; ++ cam2-ov64a40 = <&mux_in2>, "remote-endpoint:0=",<&ov64a40_2_ep>, ++ <&ov64a40_2_ep>, "remote-endpoint:0=",<&mux_in2>, ++ <&mux_in2>, "clock-noncontinuous?", ++ <&ov64a40_2>, "status=okay", ++ <&ov64a40_2_vcm>, "status=okay", ++ <&ov64a40_2>,"lens-focus:0=", <&ov64a40_2_vcm>; + + cam3-arducam-64mp = <&mux_in3>, "remote-endpoint:0=",<&arducam_64mp_3_ep>, + <&arducam_64mp_3_ep>, "remote-endpoint:0=",<&mux_in3>, +@@ -863,6 +921,12 @@ + cam3-ov2311 = <&mux_in3>, "remote-endpoint:0=",<&ov2311_3_ep>, + <&ov2311_3_ep>, "remote-endpoint:0=",<&mux_in3>, + <&ov2311_3>, "status=okay"; ++ cam3-ov64a40 = <&mux_in3>, "remote-endpoint:0=",<&ov64a40_3_ep>, ++ <&ov64a40_3_ep>, "remote-endpoint:0=",<&mux_in3>, ++ <&mux_in3>, "clock-noncontinuous?", ++ <&ov64a40_3>, "status=okay", ++ <&ov64a40_3_vcm>, "status=okay", ++ <&ov64a40_3>,"lens-focus:0=", <&ov64a40_3_vcm>; + + cam0-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_0>,"clock-frequency:0"; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ov64a40-overlay.dts +@@ -0,0 +1,91 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// Definitions for OV64A40 camera module on VC I2C bus ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2835"; ++ ++ i2c_frag: fragment@0 { ++ target = <&i2c_csi_dsi>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ #include "ov64a40.dtsi" ++ }; ++ }; ++ ++ csi_frag: fragment@1 { ++ target = <&csi1>; ++ csi: __overlay__ { ++ status = "okay"; ++ brcm,media-controller; ++ ++ port{ ++ csi_ep: endpoint{ ++ remote-endpoint = <&cam_endpoint>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c0if>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ clk_frag: fragment@3 { ++ target = <&cam1_clk>; ++ __overlay__ { ++ clock-frequency = <24000000>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c0mux>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&cam_node>; ++ __overlay__ { ++ lens-focus = <&vcm_node>; ++ }; ++ }; ++ ++ __overrides__ { ++ rotation = <&cam_node>,"rotation:0"; ++ orientation = <&cam_node>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&cam_node>, "clocks:0=",<&cam0_clk>, ++ <&cam_node>, "avdd-supply:0=",<&cam0_reg>, ++ <&vcm_node>, "vdd-supply:0=",<&cam0_reg>; ++ vcm = <&vcm_node>, "status", ++ <0>, "=5"; ++ link-frequency = <&cam_endpoint>,"link-frequencies#0"; ++ }; ++}; ++ ++&cam_node { ++ status = "okay"; ++}; ++ ++&cam_endpoint { ++ remote-endpoint = <&csi_ep>; ++}; ++ ++&vcm_node { ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ov64a40.dtsi +@@ -0,0 +1,34 @@ ++// Fragment that configures an OV64A40 ++ ++cam_node: ov64a40@36 { ++ compatible = "ovti,ov64a40"; ++ reg = <0x36>; ++ status = "disabled"; ++ ++ clocks = <&cam1_clk>; ++ clock-names = "xclk"; ++ ++ avdd-supply = <&cam1_reg>; /* 2.8v */ ++ dovdd-supply = <&cam_dummy_reg>;/* 1.8v */ ++ dvdd-supply = <&cam_dummy_reg>; /* 1.1v */ ++ ++ rotation = <180>; ++ orientation = <2>; ++ ++ port { ++ cam_endpoint: endpoint { ++ bus-type = <4>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ link-frequencies = ++ /bits/ 64 <456000000>; ++ }; ++ }; ++}; ++ ++vcm_node: bu64754@76 { ++ compatible = "rohm,bu64754"; ++ reg = <0x76>; ++ status = "disabled"; ++ vdd-supply = <&cam1_reg>; ++}; diff --git a/target/linux/bcm27xx/patches-6.1/950-1199-media-rp1-cfe-Fix-verbose-debug-print.patch b/target/linux/bcm27xx/patches-6.1/950-1199-media-rp1-cfe-Fix-verbose-debug-print.patch new file mode 100644 index 0000000000..8ff96cc568 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1199-media-rp1-cfe-Fix-verbose-debug-print.patch @@ -0,0 +1,26 @@ +From 8ef68aadaa3aa29bc2661ab44db4ddc50e77cef5 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 4 Oct 2023 11:25:16 +0300 +Subject: [PATCH] media: rp1: cfe: Fix verbose debug print + +Switch a debug print from cfe_dbg() to cfe_dbg_verbose() as it will be +printed often while streaming. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -975,8 +975,8 @@ static void cfe_buffer_queue(struct vb2_ + + if (!cfe->job_queued && cfe->job_ready && + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { +- cfe_dbg("Preparing job immediately for channel %u\n", +- node->id); ++ cfe_dbg_verbose("Preparing job immediately for channel %u\n", ++ node->id); + cfe_prepare_next_job(cfe); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1200-media-rp1-cfe-Expose-find_format_by_pix.patch b/target/linux/bcm27xx/patches-6.1/950-1200-media-rp1-cfe-Expose-find_format_by_pix.patch new file mode 100644 index 0000000000..f263648af2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1200-media-rp1-cfe-Expose-find_format_by_pix.patch @@ -0,0 +1,33 @@ +From d978e784f433346d3676b5de805b3cea36b835c4 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 16:23:58 +0300 +Subject: [PATCH] media: rp1: cfe: Expose find_format_by_pix() + +Make find_format_by_pix() accessible to other files in the driver. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -461,7 +461,7 @@ const struct cfe_fmt *find_format_by_cod + return NULL; + } + +-static const struct cfe_fmt *find_format_by_pix(u32 pixelformat) ++const struct cfe_fmt *find_format_by_pix(u32 pixelformat) + { + unsigned int i; + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -36,5 +36,6 @@ extern const struct v4l2_mbus_framefmt c + extern const struct v4l2_mbus_framefmt cfe_default_meta_format; + + const struct cfe_fmt *find_format_by_code(u32 code); ++const struct cfe_fmt *find_format_by_pix(u32 pixelformat); + + #endif diff --git a/target/linux/bcm27xx/patches-6.1/950-1201-media-rp1-cfe-Add-missing-remaps.patch b/target/linux/bcm27xx/patches-6.1/950-1201-media-rp1-cfe-Add-missing-remaps.patch new file mode 100644 index 0000000000..d6dadb6f27 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1201-media-rp1-cfe-Add-missing-remaps.patch @@ -0,0 +1,43 @@ +From cbed711f05a228d0f8f54b1b01f43d4d6489eccc Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 16:24:14 +0300 +Subject: [PATCH] media: rp1: cfe: Add missing remaps + +8-bit bayer formats are missing remap definitions. Add them. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -85,24 +85,28 @@ static const struct cfe_fmt formats[] = + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR10P, diff --git a/target/linux/bcm27xx/patches-6.1/950-1202-media-rp1-cfe-Add-missing-compressed-remaps.patch b/target/linux/bcm27xx/patches-6.1/950-1202-media-rp1-cfe-Add-missing-compressed-remaps.patch new file mode 100644 index 0000000000..92d7db369c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1202-media-rp1-cfe-Add-missing-compressed-remaps.patch @@ -0,0 +1,43 @@ +From 93c40564b94367c6ce072d66479af58afa3f08e0 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 17:14:31 +0300 +Subject: [PATCH] media: rp1: cfe: Add missing compressed remaps + +16-bit bayer formats are missing compressed remap definitions. Add them. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -197,24 +197,28 @@ static const struct cfe_fmt formats[] = + .code = MEDIA_BUS_FMT_SBGGR16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG16, + .code = MEDIA_BUS_FMT_SGBRG16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG16, + .code = MEDIA_BUS_FMT_SGRBG16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB16, + .code = MEDIA_BUS_FMT_SRGGB16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, + }, + /* PiSP Compressed Mode 1 */ + { diff --git a/target/linux/bcm27xx/patches-6.1/950-1203-media-rp1-cfe-Add-cfe_find_16bit_code-and-cfe_find_c.patch b/target/linux/bcm27xx/patches-6.1/950-1203-media-rp1-cfe-Add-cfe_find_16bit_code-and-cfe_find_c.patch new file mode 100644 index 0000000000..42c3b6f42b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1203-media-rp1-cfe-Add-cfe_find_16bit_code-and-cfe_find_c.patch @@ -0,0 +1,74 @@ +From 2e0e1d7b493dffe7baa763d499e51ba42f0bad19 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 17:14:11 +0300 +Subject: [PATCH] media: rp1: cfe: Add cfe_find_16bit_code() and + cfe_find_compressed_code() + +Add helper functions which, given an mbus code, return the 16-bit +remapped mbus code or the compressed mbus code. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 40 +++++++++++++++++++ + .../media/platform/raspberrypi/rp1_cfe/cfe.h | 2 + + 2 files changed, 42 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -473,6 +473,46 @@ const struct cfe_fmt *find_format_by_pix + return NULL; + } + ++/* ++ * Given the mbus code, find the 16 bit remapped code. Returns 0 if no remap ++ * possible. ++ */ ++u32 cfe_find_16bit_code(u32 code) ++{ ++ const struct cfe_fmt *cfe_fmt; ++ ++ cfe_fmt = find_format_by_code(code); ++ ++ if (!cfe_fmt || !cfe_fmt->remap[CFE_REMAP_16BIT]) ++ return 0; ++ ++ cfe_fmt = find_format_by_pix(cfe_fmt->remap[CFE_REMAP_16BIT]); ++ if (!cfe_fmt) ++ return 0; ++ ++ return cfe_fmt->code; ++} ++ ++/* ++ * Given the mbus code, find the 8 bit compressed code. Returns 0 if no remap ++ * possible. ++ */ ++u32 cfe_find_compressed_code(u32 code) ++{ ++ const struct cfe_fmt *cfe_fmt; ++ ++ cfe_fmt = find_format_by_code(code); ++ ++ if (!cfe_fmt || !cfe_fmt->remap[CFE_REMAP_COMPRESSED]) ++ return 0; ++ ++ cfe_fmt = find_format_by_pix(cfe_fmt->remap[CFE_REMAP_COMPRESSED]); ++ if (!cfe_fmt) ++ return 0; ++ ++ return cfe_fmt->code; ++} ++ + static int cfe_calc_format_size_bpl(struct cfe_device *cfe, + const struct cfe_fmt *fmt, + struct v4l2_format *f) +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -37,5 +37,7 @@ extern const struct v4l2_mbus_framefmt c + + const struct cfe_fmt *find_format_by_code(u32 code); + const struct cfe_fmt *find_format_by_pix(u32 pixelformat); ++u32 cfe_find_16bit_code(u32 code); ++u32 cfe_find_compressed_code(u32 code); + + #endif diff --git a/target/linux/bcm27xx/patches-6.1/950-1204-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch b/target/linux/bcm27xx/patches-6.1/950-1204-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch new file mode 100644 index 0000000000..d9b8d264d3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1204-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch @@ -0,0 +1,95 @@ +From eaa8a0ae14a1ca797c1896e9dafbefa1fa51a617 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 16:25:10 +0300 +Subject: [PATCH] media: rp1: csi2: Fix csi2_pad_set_fmt() + +The CSI-2 subdev's set_fmt currently allows setting the source and sink +pad formats quite freely. This is not right, as the CSI-2 block can only +do one of the following when processing the stream: 1) pass through as +is, 2) expand to 16-bits, 3) compress. + +The csi2_pad_set_fmt() should take this into account, and only allow +changing the source side mbus code, compared to the sink side format. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 61 +++++++++++++++---- + 1 file changed, 48 insertions(+), 13 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -438,25 +438,60 @@ static int csi2_pad_set_fmt(struct v4l2_ + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *format) + { +- struct v4l2_mbus_framefmt *fmt; +- const struct cfe_fmt *cfe_fmt; +- +- /* TODO: format validation */ ++ if (format->pad < CSI2_NUM_CHANNELS) { ++ /* ++ * Store the sink pad format and propagate it to the source pad. ++ */ ++ ++ struct v4l2_mbus_framefmt *fmt; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ if (!fmt) ++ return -EINVAL; + +- cfe_fmt = find_format_by_code(format->format.code); +- if (!cfe_fmt) +- cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ *fmt = format->format; + +- format->format.code = cfe_fmt->code; ++ fmt = v4l2_subdev_get_pad_format(sd, state, ++ format->pad + CSI2_NUM_CHANNELS); ++ if (!fmt) ++ return -EINVAL; + +- fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); +- *fmt = format->format; ++ format->format.field = V4L2_FIELD_NONE; + +- if (format->pad < CSI2_NUM_CHANNELS) { +- /* Propagate to the source pad */ +- fmt = v4l2_subdev_get_pad_format(sd, state, +- format->pad + CSI2_NUM_CHANNELS); + *fmt = format->format; ++ } else { ++ /* ++ * Only allow changing the source pad mbus code. ++ */ ++ ++ struct v4l2_mbus_framefmt *sink_fmt, *source_fmt; ++ u32 sink_code; ++ u32 code; ++ ++ sink_fmt = v4l2_subdev_get_pad_format(sd, state, ++ format->pad - CSI2_NUM_CHANNELS); ++ if (!sink_fmt) ++ return -EINVAL; ++ ++ source_fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ if (!source_fmt) ++ return -EINVAL; ++ ++ sink_code = sink_fmt->code; ++ code = format->format.code; ++ ++ /* ++ * If the source code from the user does not match the code in ++ * the sink pad, check that the source code matches either the ++ * 16-bit version or the compressed version of the sink code. ++ */ ++ ++ if (code != sink_code && ++ (code == cfe_find_16bit_code(sink_code) || ++ code == cfe_find_compressed_code(sink_code))) ++ source_fmt->code = code; ++ ++ format->format.code = source_fmt->code; + } + + return 0; diff --git a/target/linux/bcm27xx/patches-6.1/950-1205-media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch b/target/linux/bcm27xx/patches-6.1/950-1205-media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch new file mode 100644 index 0000000000..202fe2946d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1205-media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch @@ -0,0 +1,104 @@ +From 214e8134842a338215831f2efa6d730f413c5ec4 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 17:15:20 +0300 +Subject: [PATCH] media: rp1: fe: Fix pisp_fe_pad_set_fmt() + +pisp_fe_pad_set_fmt() allows setting the pad formats quite freely. This +is not correct, and the function should only allow formats as supported +by the hardware. Fix this by: + +Allow no format changes for FE_CONFIG_PAD and FE_STATS_PAD. They should +always be the hardcoded initial ones. + +Allow setting FE_STREAM_PAD freely (but the mbus code must be +supported), and propagate the format to the FE_OUTPUT0_PAD and +FE_OUTPUT1_PAD pads. + +Allow changing the mbus code for FE_OUTPUT0_PAD and FE_OUTPUT1_PAD pads +only if the mbus code is the compressed version of the sink side code. + +TODO: FE supports scaling and cropping. This should be represented here +too? + +Signed-off-by: Tomi Valkeinen +--- + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 59 +++++++++++++++---- + 1 file changed, 48 insertions(+), 11 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -433,26 +433,63 @@ static int pisp_fe_pad_set_fmt(struct v4 + + switch (format->pad) { + case FE_STREAM_PAD: +- case FE_OUTPUT0_PAD: +- case FE_OUTPUT1_PAD: + cfe_fmt = find_format_by_code(format->format.code); + if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) + cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16); + + format->format.code = cfe_fmt->code; ++ format->format.field = V4L2_FIELD_NONE; + +- break; ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_STREAM_PAD); ++ *fmt = format->format; + +- case FE_STATS_PAD: +- case FE_CONFIG_PAD: +- format->format.code = MEDIA_BUS_FMT_FIXED; +- break; +- } ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT0_PAD); ++ *fmt = format->format; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT1_PAD); ++ *fmt = format->format; ++ ++ return 0; + +- fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); +- *fmt = format->format; ++ case FE_OUTPUT0_PAD: ++ case FE_OUTPUT1_PAD: { ++ /* ++ * TODO: we should allow scaling and cropping by allowing the ++ * user to set the size here. ++ */ ++ struct v4l2_mbus_framefmt *sink_fmt, *source_fmt; ++ u32 sink_code; ++ u32 code; ++ ++ sink_fmt = v4l2_subdev_get_pad_format(sd, state, FE_STREAM_PAD); ++ if (!sink_fmt) ++ return -EINVAL; ++ ++ source_fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ if (!source_fmt) ++ return -EINVAL; ++ ++ sink_code = sink_fmt->code; ++ code = format->format.code; ++ ++ /* ++ * If the source code from the user does not match the code in ++ * the sink pad, check that the source code matches the ++ * compressed version of the sink code. ++ */ ++ ++ if (code != sink_code && ++ code == cfe_find_compressed_code(sink_code)) ++ source_fmt->code = code; ++ ++ return 0; ++ } + +- return 0; ++ case FE_CONFIG_PAD: ++ case FE_STATS_PAD: ++ default: ++ return v4l2_subdev_get_fmt(sd, state, format); ++ } + } + + static int pisp_fe_link_validate(struct v4l2_subdev *sd, diff --git a/target/linux/bcm27xx/patches-6.1/950-1206-media-rp1-csi2-Use-get_frame_desc-to-get-CSI-2-VC-an.patch b/target/linux/bcm27xx/patches-6.1/950-1206-media-rp1-csi2-Use-get_frame_desc-to-get-CSI-2-VC-an.patch new file mode 100644 index 0000000000..bd5789a1b3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1206-media-rp1-csi2-Use-get_frame_desc-to-get-CSI-2-VC-an.patch @@ -0,0 +1,146 @@ +From 425a6b752c38b50c97220db37a67b18b281f56e5 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 21 Sep 2023 15:28:20 +0300 +Subject: [PATCH] media: rp1: csi2: Use get_frame_desc to get CSI-2 VC and DT + +Use get_frame_desc pad op for asking the CSI-2 VC and DT from the source +device driver, instead of hardcoding to VC 0, and getting the DT from a +formats table. To keep backward compatibility with sources that do not +implement get_frame_desc, implement a fallback mechanism that always +uses VC 0, and gets the DT from the formats table, based on the CSI2's +sink pad's format. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 4 +- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 75 ++++++++++++++++++- + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 2 +- + 3 files changed, 77 insertions(+), 4 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -838,7 +838,7 @@ static void cfe_start_channel(struct cfe + * this is handled by the CSI2 AUTO_ARM mode. + */ + csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel, +- fmt->csi_dt, CSI2_MODE_FE_STREAMING, ++ CSI2_MODE_FE_STREAMING, + true, false, width, height); + csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1); + pisp_fe_start(&cfe->fe); +@@ -872,7 +872,7 @@ static void cfe_start_channel(struct cfe + } + } + /* Unconditionally start this CSI2 channel. */ +- csi2_start_channel(&cfe->csi2, node->id, fmt->csi_dt, ++ csi2_start_channel(&cfe->csi2, node->id, + mode, + /* Auto arm */ + false, +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -324,12 +324,84 @@ void csi2_set_compression(struct csi2_de + csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression); + } + ++static int csi2_get_vc_dt_fallback(struct csi2_device *csi2, ++ unsigned int channel, u8 *vc, u8 *dt) ++{ ++ struct v4l2_subdev *sd = &csi2->sd; ++ struct v4l2_subdev_state *state; ++ struct v4l2_mbus_framefmt *fmt; ++ const struct cfe_fmt *cfe_fmt; ++ ++ state = v4l2_subdev_get_locked_active_state(sd); ++ ++ /* Without Streams API, the channel number matches the sink pad */ ++ fmt = v4l2_subdev_get_pad_format(sd, state, channel); ++ if (!fmt) ++ return -EINVAL; ++ ++ cfe_fmt = find_format_by_code(fmt->code); ++ if (!cfe_fmt) ++ return -EINVAL; ++ ++ *vc = 0; ++ *dt = cfe_fmt->csi_dt; ++ ++ return 0; ++} ++ ++static int csi2_get_vc_dt(struct csi2_device *csi2, unsigned int channel, ++ u8 *vc, u8 *dt) ++{ ++ struct v4l2_mbus_frame_desc remote_desc; ++ const struct media_pad *remote_pad; ++ struct v4l2_subdev *source_sd; ++ int ret; ++ ++ /* Without Streams API, the channel number matches the sink pad */ ++ remote_pad = media_pad_remote_pad_first(&csi2->pad[channel]); ++ if (!remote_pad) ++ return -EPIPE; ++ ++ source_sd = media_entity_to_v4l2_subdev(remote_pad->entity); ++ ++ ret = v4l2_subdev_call(source_sd, pad, get_frame_desc, ++ remote_pad->index, &remote_desc); ++ if (ret == -ENOIOCTLCMD) { ++ csi2_dbg("source does not support get_frame_desc, use fallback\n"); ++ return csi2_get_vc_dt_fallback(csi2, channel, vc, dt); ++ } else if (ret) { ++ csi2_err("Failed to get frame descriptor\n"); ++ return ret; ++ } ++ ++ if (remote_desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) { ++ csi2_err("Frame descriptor does not describe CSI-2 link"); ++ return -EINVAL; ++ } ++ ++ if (remote_desc.num_entries != 1) { ++ csi2_err("Frame descriptor does not have a single entry"); ++ return -EINVAL; ++ } ++ ++ *vc = remote_desc.entry[0].bus.csi2.vc; ++ *dt = remote_desc.entry[0].bus.csi2.dt; ++ ++ return 0; ++} ++ + void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, +- u16 dt, enum csi2_mode mode, bool auto_arm, ++ enum csi2_mode mode, bool auto_arm, + bool pack_bytes, unsigned int width, + unsigned int height) + { + u32 ctrl; ++ int ret; ++ u8 vc, dt; ++ ++ ret = csi2_get_vc_dt(csi2, channel, &vc, &dt); ++ if (ret) ++ return; + + csi2_dbg("%s [%u]\n", __func__, channel); + +@@ -369,6 +441,7 @@ void csi2_start_channel(struct csi2_devi + csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0); + } + ++ set_field(&ctrl, vc, VC_MASK); + set_field(&ctrl, dt, DT_MASK); + csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl); + csi2->num_lines[channel] = height; +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -79,7 +79,7 @@ void csi2_set_compression(struct csi2_de + enum csi2_compression_mode mode, unsigned int shift, + unsigned int offset); + void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, +- u16 dt, enum csi2_mode mode, bool auto_arm, ++ enum csi2_mode mode, bool auto_arm, + bool pack_bytes, unsigned int width, + unsigned int height); + void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel); diff --git a/target/linux/bcm27xx/patches-6.1/950-1207-media-rp1-cfe-Add-is_image_node.patch b/target/linux/bcm27xx/patches-6.1/950-1207-media-rp1-cfe-Add-is_image_node.patch new file mode 100644 index 0000000000..ad589d79cf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1207-media-rp1-cfe-Add-is_image_node.patch @@ -0,0 +1,91 @@ +From 2b6570e66f2769110311593f52f88dba3271a278 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 22 Sep 2023 13:47:10 +0300 +Subject: [PATCH] media: rp1: cfe: Add is_image_node() + +The hardware supports streaming from memory (in addition to streaming +from the CSI-2 RX), but the driver does not support this at the moment. + +There are multiple places in the driver which uses +is_image_output_node(), even if the "output" part is not relevant. Thus, +in a minor preparation for the possible support for streaming from +memory, and to make it more obvious that the pieces of code are not +about the "output", add is_image_node() which will return true for both +input and output video nodes. + +While at it, reformat also the metadata related macros to fit inside 80 +columns. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 28 +++++++++++-------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -199,13 +199,20 @@ static const struct node_description nod + + #define is_fe_node(node) (((node)->id) >= FE_OUT0) + #define is_csi2_node(node) (!is_fe_node(node)) +-#define is_image_output_node(node) \ ++ ++#define is_image_output_node(node) \ + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) +-#define is_meta_output_node(node) \ ++#define is_image_input_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++#define is_image_node(node) \ ++ (is_image_output_node(node) || is_image_input_node(node)) ++ ++#define is_meta_output_node(node) \ + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE) +-#define is_meta_input_node(node) \ ++#define is_meta_input_node(node) \ + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT) +-#define is_meta_node(node) (is_meta_output_node(node) || is_meta_input_node(node)) ++#define is_meta_node(node) \ ++ (is_meta_output_node(node) || is_meta_input_node(node)) + + /* To track state across all nodes. */ + #define NUM_STATES 5 +@@ -426,7 +433,7 @@ static int format_show(struct seq_file * + seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i, + node_desc[i].name, state); + +- if (is_image_output_node(node)) ++ if (is_image_node(node)) + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n" + "resolution: %ux%u\nbpl: %u\nsize: %u\n", + V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat), +@@ -940,9 +947,8 @@ static int cfe_queue_setup(struct vb2_qu + { + struct cfe_node *node = vb2_get_drv_priv(vq); + struct cfe_device *cfe = node->cfe; +- unsigned int size = is_image_output_node(node) ? +- node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ unsigned int size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +@@ -973,8 +979,8 @@ static int cfe_buffer_prepare(struct vb2 + cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, + node_desc[node->id].name, vb); + +- size = is_image_output_node(node) ? node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; + if (vb2_plane_size(vb, 0) < size) { + cfe_err("data will not fit into plane (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); +@@ -1757,7 +1763,7 @@ static int cfe_register_node(struct cfe_ + node->cfe = cfe; + node->id = id; + +- if (is_image_output_node(node)) { ++ if (is_image_node(node)) { + fmt = find_format_by_code(cfe_default_format.code); + if (!fmt) { + cfe_err("Failed to find format code\n"); diff --git a/target/linux/bcm27xx/patches-6.1/950-1208-media-rp1-cfe-Dual-purpose-video-nodes.patch b/target/linux/bcm27xx/patches-6.1/950-1208-media-rp1-cfe-Dual-purpose-video-nodes.patch new file mode 100644 index 0000000000..f68aa3975d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1208-media-rp1-cfe-Dual-purpose-video-nodes.patch @@ -0,0 +1,621 @@ +From c54b8d2fc79c684deacc81a94f6baa1cb56c62be Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 27 Sep 2023 17:18:09 +0300 +Subject: [PATCH] media: rp1: cfe: Dual purpose video nodes + +The RP1 CSI-2 DMA can capture both video and metadata just fine, but at +the moment the video nodes are only set to support either video or +metadata. + +Make the changes to support both video and metadata. This mostly means +tracking both video format and metadata format separately for each video +node, and using vb2_queue_change_type() to change the vb2 queue type +when needed. + +Briefly, this means that the user can get/set both video and meta +formats to a single video node. The vb2 queue buffer type will be +changed when the user calls REQBUFS or CREATE_BUFS ioctls. This buffer +type will be then used as the "mode" for the video node when the user +starts the streaming, and based on that either the video or the meta +format will be used. + +A bunch of macros are added (node_supports_xxx()), which tell if a node +can support a particular mode, whereas the existing macros +(is_xxx_node()) will tell if the node is currently in a particular mode. +Note that the latter will only work correctly between the start of the +streaming and the end of the streaming, and thus should be only used in +those code paths. + +However, as the userspace (libcamera) does not support dual purpose +video nodes, for the time being let's keep the second video node as +V4L2_CAP_META_CAPTURE only to keep the userspace working. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 271 ++++++++++++------ + 1 file changed, 182 insertions(+), 89 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -116,7 +116,7 @@ const struct v4l2_mbus_framefmt cfe_defa + enum node_ids { + /* CSI2 HW output nodes first. */ + CSI2_CH0, +- CSI2_CH1_EMBEDDED, ++ CSI2_CH1, + CSI2_CH2, + CSI2_CH3, + /* FE only nodes from here on. */ +@@ -130,8 +130,7 @@ enum node_ids { + struct node_description { + unsigned int id; + const char *name; +- enum v4l2_buf_type buf_type; +- unsigned int cap; ++ unsigned int caps; + unsigned int pad_flags; + unsigned int link_pad; + }; +@@ -140,58 +139,55 @@ struct node_description { + static const struct node_description node_desc[NUM_NODES] = { + [CSI2_CH0] = { + .name = "csi2_ch0", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 0 + }, +- /* This node is assigned for the embedded data channel! */ +- [CSI2_CH1_EMBEDDED] = { ++ /* ++ * TODO: This node should be named "csi2_ch1" and the caps should be set ++ * to both video and meta capture. However, to keep compatibility with ++ * the current libcamera, keep the name as "embedded" and support ++ * only meta capture. ++ */ ++ [CSI2_CH1] = { + .name = "embedded", +- .buf_type = V4L2_BUF_TYPE_META_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 1 + }, + [CSI2_CH2] = { + .name = "csi2_ch2", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 2 + }, + [CSI2_CH3] = { + .name = "csi2_ch3", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 3 + }, + [FE_OUT0] = { + .name = "fe_image0", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_OUTPUT0_PAD + }, + [FE_OUT1] = { + .name = "fe_image1", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_OUTPUT1_PAD + }, + [FE_STATS] = { + .name = "fe_stats", +- .buf_type = V4L2_BUF_TYPE_META_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_STATS_PAD + }, + [FE_CONFIG] = { + .name = "fe_config", +- .buf_type = V4L2_BUF_TYPE_META_OUTPUT, +- .cap = V4L2_CAP_META_OUTPUT, ++ .caps = V4L2_CAP_META_OUTPUT, + .pad_flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_CONFIG_PAD + }, +@@ -200,17 +196,29 @@ static const struct node_description nod + #define is_fe_node(node) (((node)->id) >= FE_OUT0) + #define is_csi2_node(node) (!is_fe_node(node)) + ++#define node_supports_image_output(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_VIDEO_CAPTURE)) ++#define node_supports_meta_output(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_META_CAPTURE)) ++#define node_supports_image_input(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_VIDEO_OUTPUT)) ++#define node_supports_meta_input(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_META_OUTPUT)) ++#define node_supports_image(node) \ ++ (node_supports_image_output(node) || node_supports_image_input(node)) ++#define node_supports_meta(node) \ ++ (node_supports_meta_output(node) || node_supports_meta_input(node)) ++ + #define is_image_output_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + #define is_image_input_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + #define is_image_node(node) \ + (is_image_output_node(node) || is_image_input_node(node)) +- + #define is_meta_output_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_CAPTURE) + #define is_meta_input_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_OUTPUT) + #define is_meta_node(node) \ + (is_meta_output_node(node) || is_meta_input_node(node)) + +@@ -250,7 +258,9 @@ struct cfe_node { + /* Pointer pointing to next v4l2_buffer */ + struct cfe_buffer *next_frm; + /* Used to store current pixel format */ +- struct v4l2_format fmt; ++ struct v4l2_format vid_fmt; ++ /* Used to store current meta format */ ++ struct v4l2_format meta_fmt; + /* Buffer queue used in video-buf */ + struct vb2_queue buffer_queue; + /* Queue of filled frames */ +@@ -433,20 +443,21 @@ static int format_show(struct seq_file * + seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i, + node_desc[i].name, state); + +- if (is_image_node(node)) ++ if (node_supports_image(node)) + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n" + "resolution: %ux%u\nbpl: %u\nsize: %u\n", +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat), +- node->fmt.fmt.pix.pixelformat, +- node->fmt.fmt.pix.width, +- node->fmt.fmt.pix.height, +- node->fmt.fmt.pix.bytesperline, +- node->fmt.fmt.pix.sizeimage); +- else ++ V4L2_FOURCC_CONV_ARGS(node->vid_fmt.fmt.pix.pixelformat), ++ node->vid_fmt.fmt.pix.pixelformat, ++ node->vid_fmt.fmt.pix.width, ++ node->vid_fmt.fmt.pix.height, ++ node->vid_fmt.fmt.pix.bytesperline, ++ node->vid_fmt.fmt.pix.sizeimage); ++ ++ if (node_supports_meta(node)) + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\nsize: %u\n", +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat), +- node->fmt.fmt.meta.dataformat, +- node->fmt.fmt.meta.buffersize); ++ V4L2_FOURCC_CONV_ARGS(node->meta_fmt.fmt.meta.dataformat), ++ node->meta_fmt.fmt.meta.dataformat, ++ node->meta_fmt.fmt.meta.buffersize); + } + + return 0; +@@ -571,11 +582,11 @@ static void cfe_schedule_next_csi2_job(s + node_desc[node->id].name, &buf->vb.vb2_buf); + + if (is_meta_node(node)) { +- size = node->fmt.fmt.meta.buffersize; ++ size = node->meta_fmt.fmt.meta.buffersize; + stride = 0; + } else { +- size = node->fmt.fmt.pix.sizeimage; +- stride = node->fmt.fmt.pix.bytesperline; ++ size = node->vid_fmt.fmt.pix.sizeimage; ++ stride = node->vid_fmt.fmt.pix.bytesperline; + } + + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); +@@ -867,10 +878,10 @@ static void cfe_start_channel(struct cfe + width = source_fmt->width; + height = source_fmt->height; + +- if (node->fmt.fmt.pix.pixelformat == ++ if (node->vid_fmt.fmt.pix.pixelformat == + fmt->remap[CFE_REMAP_16BIT]) + mode = CSI2_MODE_REMAP; +- else if (node->fmt.fmt.pix.pixelformat == ++ else if (node->vid_fmt.fmt.pix.pixelformat == + fmt->remap[CFE_REMAP_COMPRESSED]) { + mode = CSI2_MODE_COMPRESSED; + csi2_set_compression(&cfe->csi2, node->id, +@@ -884,7 +895,7 @@ static void cfe_start_channel(struct cfe + /* Auto arm */ + false, + /* Pack bytes */ +- node->id == CSI2_CH1_EMBEDDED ? true : false, ++ is_meta_node(node) ? true : false, + width, height); + } + +@@ -947,10 +958,11 @@ static int cfe_queue_setup(struct vb2_qu + { + struct cfe_node *node = vb2_get_drv_priv(vq); + struct cfe_device *cfe = node->cfe; +- unsigned int size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ unsigned int size = is_image_node(node) ? node->vid_fmt.fmt.pix.sizeimage : ++ node->meta_fmt.fmt.meta.buffersize; + +- cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name, ++ node->buffer_queue.type); + + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; +@@ -979,8 +991,8 @@ static int cfe_buffer_prepare(struct vb2 + cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, + node_desc[node->id].name, vb); + +- size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ size = is_image_node(node) ? node->vid_fmt.fmt.pix.sizeimage : ++ node->meta_fmt.fmt.meta.buffersize; + if (vb2_plane_size(vb, 0) < size) { + cfe_err("data will not fit into plane (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); +@@ -995,8 +1007,8 @@ static int cfe_buffer_prepare(struct vb2 + + memcpy(&b->config, addr, sizeof(struct pisp_fe_config)); + return pisp_fe_validate_config(&cfe->fe, &b->config, +- &cfe->node[FE_OUT0].fmt, +- &cfe->node[FE_OUT1].fmt); ++ &cfe->node[FE_OUT0].vid_fmt, ++ &cfe->node[FE_OUT1].vid_fmt); + } + + return 0; +@@ -1256,7 +1268,7 @@ static int cfe_enum_fmt_vid_cap(struct f + struct cfe_device *cfe = node->cfe; + unsigned int i, j; + +- if (!is_image_output_node(node)) ++ if (!node_supports_image_output(node)) + return -EINVAL; + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); +@@ -1292,10 +1304,10 @@ static int cfe_g_fmt(struct file *file, + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +- if (f->type != node->buffer_queue.type) ++ if (!node_supports_image(node)) + return -EINVAL; + +- *f = node->fmt; ++ *f = node->vid_fmt; + + return 0; + } +@@ -1310,7 +1322,7 @@ static int try_fmt_vid_cap(struct cfe_no + f->fmt.pix.width, f->fmt.pix.height, + V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat)); + +- if (!is_image_output_node(node)) ++ if (!node_supports_image_output(node)) + return -EINVAL; + + /* +@@ -1351,11 +1363,11 @@ static int cfe_s_fmt_vid_cap(struct file + if (ret) + return ret; + +- node->fmt = *f; ++ node->vid_fmt = *f; + + cfe_dbg("%s: Set %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", __func__, +- node->fmt.fmt.pix.width, node->fmt.fmt.pix.height, +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat)); ++ node->vid_fmt.fmt.pix.width, node->vid_fmt.fmt.pix.height, ++ V4L2_FOURCC_CONV_ARGS(node->vid_fmt.fmt.pix.pixelformat)); + + return 0; + } +@@ -1379,11 +1391,11 @@ static int cfe_enum_fmt_meta(struct file + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +- if (!is_meta_node(node) || f->index != 0) ++ if (!node_supports_meta(node) || f->index != 0) + return -EINVAL; + + switch (node->id) { +- case CSI2_CH1_EMBEDDED: ++ case CSI2_CH0...CSI2_CH3: + f->pixelformat = V4L2_META_FMT_SENSOR_DATA; + return 0; + case FE_STATS: +@@ -1399,8 +1411,11 @@ static int cfe_enum_fmt_meta(struct file + + static int try_fmt_meta(struct cfe_node *node, struct v4l2_format *f) + { ++ if (!node_supports_meta(node)) ++ return -EINVAL; ++ + switch (node->id) { +- case CSI2_CH1_EMBEDDED: ++ case CSI2_CH0...CSI2_CH3: + f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA; + if (!f->fmt.meta.buffersize) + f->fmt.meta.buffersize = DEFAULT_EMBEDDED_SIZE; +@@ -1422,6 +1437,21 @@ static int try_fmt_meta(struct cfe_node + return -EINVAL; + } + ++static int cfe_g_fmt_meta(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (!node_supports_meta(node)) ++ return -EINVAL; ++ ++ *f = node->meta_fmt; ++ ++ return 0; ++} ++ + static int cfe_s_fmt_meta(struct file *file, void *priv, struct v4l2_format *f) + { + struct cfe_node *node = video_drvdata(file); +@@ -1434,17 +1464,17 @@ static int cfe_s_fmt_meta(struct file *f + if (vb2_is_busy(q)) + return -EBUSY; + +- if (f->type != node->buffer_queue.type) ++ if (!node_supports_meta(node)) + return -EINVAL; + + ret = try_fmt_meta(node, f); + if (ret) + return ret; + +- node->fmt = *f; ++ node->meta_fmt = *f; + + cfe_dbg("%s: Set " V4L2_FOURCC_CONV "\n", __func__, +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat)); ++ V4L2_FOURCC_CONV_ARGS(node->meta_fmt.fmt.meta.dataformat)); + + return 0; + } +@@ -1491,6 +1521,52 @@ static int cfe_enum_framesizes(struct fi + return 0; + } + ++static int cfe_vb2_ioctl_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *p) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct cfe_node *node = video_get_drvdata(vdev); ++ struct cfe_device *cfe = node->cfe; ++ int ret; ++ ++ cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name, ++ p->type); ++ ++ if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ p->type != V4L2_BUF_TYPE_META_CAPTURE && ++ p->type != V4L2_BUF_TYPE_META_OUTPUT) ++ return -EINVAL; ++ ++ ret = vb2_queue_change_type(vdev->queue, p->type); ++ if (ret) ++ return ret; ++ ++ return vb2_ioctl_reqbufs(file, priv, p); ++} ++ ++static int cfe_vb2_ioctl_create_bufs(struct file *file, void *priv, ++ struct v4l2_create_buffers *p) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct cfe_node *node = video_get_drvdata(vdev); ++ struct cfe_device *cfe = node->cfe; ++ int ret; ++ ++ cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name, ++ p->format.type); ++ ++ if (p->format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ p->format.type != V4L2_BUF_TYPE_META_CAPTURE && ++ p->format.type != V4L2_BUF_TYPE_META_OUTPUT) ++ return -EINVAL; ++ ++ ret = vb2_queue_change_type(vdev->queue, p->format.type); ++ if (ret) ++ return ret; ++ ++ return vb2_ioctl_create_bufs(file, priv, p); ++} ++ + static int cfe_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) + { +@@ -1498,12 +1574,13 @@ static int cfe_subscribe_event(struct v4 + + switch (sub->type) { + case V4L2_EVENT_FRAME_SYNC: +- if (!is_image_output_node(node)) ++ if (!node_supports_image_output(node)) + break; + + return v4l2_event_subscribe(fh, sub, 2, NULL); + case V4L2_EVENT_SOURCE_CHANGE: +- if (is_meta_input_node(node)) ++ if (!node_supports_image_output(node) && ++ !node_supports_meta_output(node)) + break; + + return v4l2_event_subscribe(fh, sub, 4, NULL); +@@ -1520,19 +1597,19 @@ static const struct v4l2_ioctl_ops cfe_i + .vidioc_try_fmt_vid_cap = cfe_try_fmt_vid_cap, + + .vidioc_enum_fmt_meta_cap = cfe_enum_fmt_meta, +- .vidioc_g_fmt_meta_cap = cfe_g_fmt, ++ .vidioc_g_fmt_meta_cap = cfe_g_fmt_meta, + .vidioc_s_fmt_meta_cap = cfe_s_fmt_meta, + .vidioc_try_fmt_meta_cap = cfe_try_fmt_meta, + + .vidioc_enum_fmt_meta_out = cfe_enum_fmt_meta, +- .vidioc_g_fmt_meta_out = cfe_g_fmt, ++ .vidioc_g_fmt_meta_out = cfe_g_fmt_meta, + .vidioc_s_fmt_meta_out = cfe_s_fmt_meta, + .vidioc_try_fmt_meta_out = cfe_try_fmt_meta, + + .vidioc_enum_framesizes = cfe_enum_framesizes, + +- .vidioc_reqbufs = vb2_ioctl_reqbufs, +- .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_reqbufs = cfe_vb2_ioctl_reqbufs, ++ .vidioc_create_bufs = cfe_vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, +@@ -1610,7 +1687,7 @@ static int cfe_video_link_validate(struc + } + + if (is_image_output_node(node)) { +- struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix; ++ struct v4l2_pix_format *pix_fmt = &node->vid_fmt.fmt.pix; + const struct cfe_fmt *fmt = NULL; + unsigned int i; + +@@ -1636,8 +1713,8 @@ static int cfe_video_link_validate(struc + ret = -EINVAL; + goto out; + } +- } else if (node->id == CSI2_CH1_EMBEDDED) { +- struct v4l2_meta_format *meta_fmt = &node->fmt.fmt.meta; ++ } else if (is_csi2_node(node) && is_meta_output_node(node)) { ++ struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta; + + if (source_fmt->width * source_fmt->height != + meta_fmt->buffersize || +@@ -1698,15 +1775,17 @@ static int cfe_video_link_notify(struct + + if (link->source->entity != csi2) + return 0; +- if (link->sink->index != 0) ++ if (link->sink->entity != fe) + return 0; +- if (link->source->index == node_desc[CSI2_CH1_EMBEDDED].link_pad) ++ if (link->sink->index != 0) + return 0; + + cfe->fe_csi2_channel = -1; +- if (link->sink->entity == fe && (link->flags & MEDIA_LNK_FL_ENABLED)) { ++ if (link->flags & MEDIA_LNK_FL_ENABLED) { + if (link->source->index == node_desc[CSI2_CH0].link_pad) + cfe->fe_csi2_channel = CSI2_CH0; ++ else if (link->source->index == node_desc[CSI2_CH1].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH1; + else if (link->source->index == node_desc[CSI2_CH2].link_pad) + cfe->fe_csi2_channel = CSI2_CH2; + else if (link->source->index == node_desc[CSI2_CH3].link_pad) +@@ -1763,30 +1842,42 @@ static int cfe_register_node(struct cfe_ + node->cfe = cfe; + node->id = id; + +- if (is_image_node(node)) { ++ if (node_supports_image(node)) { ++ if (node_supports_image_output(node)) ++ node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ else ++ node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ + fmt = find_format_by_code(cfe_default_format.code); + if (!fmt) { + cfe_err("Failed to find format code\n"); + return -EINVAL; + } + +- node->fmt.fmt.pix.pixelformat = fmt->fourcc; +- v4l2_fill_pix_format(&node->fmt.fmt.pix, &cfe_default_format); ++ node->vid_fmt.fmt.pix.pixelformat = fmt->fourcc; ++ v4l2_fill_pix_format(&node->vid_fmt.fmt.pix, &cfe_default_format); + +- ret = try_fmt_vid_cap(node, &node->fmt); ++ ret = try_fmt_vid_cap(node, &node->vid_fmt); + if (ret) + return ret; +- } else { +- ret = try_fmt_meta(node, &node->fmt); ++ } ++ ++ if (node_supports_meta(node)) { ++ if (node_supports_meta_output(node)) ++ node->meta_fmt.type = V4L2_BUF_TYPE_META_CAPTURE; ++ else ++ node->meta_fmt.type = V4L2_BUF_TYPE_META_OUTPUT; ++ ++ ret = try_fmt_meta(node, &node->meta_fmt); + if (ret) + return ret; + } +- node->fmt.type = node_desc[id].buf_type; + + mutex_init(&node->lock); + + q = &node->buffer_queue; +- q->type = node_desc[id].buf_type; ++ q->type = node_supports_image(node) ? node->vid_fmt.type : ++ node->meta_fmt.type; + q->io_modes = VB2_MMAP | VB2_DMABUF; + q->drv_priv = node; + q->ops = &cfe_video_qops; +@@ -1812,11 +1903,13 @@ static int cfe_register_node(struct cfe_ + vdev->ioctl_ops = &cfe_ioctl_ops; + vdev->entity.ops = &cfe_media_entity_ops; + vdev->v4l2_dev = &cfe->v4l2_dev; +- vdev->vfl_dir = (is_image_output_node(node) || is_meta_output_node(node)) +- ? VFL_DIR_RX : VFL_DIR_TX; ++ vdev->vfl_dir = (node_supports_image_output(node) || ++ node_supports_meta_output(node)) ? ++ VFL_DIR_RX : ++ VFL_DIR_TX; + vdev->queue = q; + vdev->lock = &node->lock; +- vdev->device_caps = node_desc[id].cap; ++ vdev->device_caps = node_desc[id].caps; + vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; + + /* Define the device names */ +@@ -1829,7 +1922,7 @@ static int cfe_register_node(struct cfe_ + node->pad.flags = node_desc[id].pad_flags; + media_entity_pads_init(&vdev->entity, 1, &node->pad); + +- if (is_meta_node(node)) { ++ if (!node_supports_image(node)) { + v4l2_disable_ioctl(&node->video_dev, + VIDIOC_ENUM_FRAMEINTERVALS); + v4l2_disable_ioctl(&node->video_dev, +@@ -1907,7 +2000,7 @@ static int cfe_link_node_pads(struct cfe + if (ret) + return ret; + +- if (node->id != CSI2_CH1_EMBEDDED) { ++ if (node_supports_image(node)) { + /* CSI2 channel # -> FE Input */ + ret = media_create_pad_link(&cfe->csi2.sd.entity, + node_desc[i].link_pad, diff --git a/target/linux/bcm27xx/patches-6.1/950-1209-media-rp1-Drop-LE-handling.patch b/target/linux/bcm27xx/patches-6.1/950-1209-media-rp1-Drop-LE-handling.patch new file mode 100644 index 0000000000..1d6e396f1c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1209-media-rp1-Drop-LE-handling.patch @@ -0,0 +1,127 @@ +From dad296088dffbaf55c1e61cbdc3f7cb1eb504ca6 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 16 May 2023 15:51:54 +0300 +Subject: [PATCH] media: rp1: Drop LE handling + +The driver registers for line-end interrupts, but never uses them. This +just causes extra interrupt load, with more complexity in the driver. + +Drop the LE handling. It can easily be added back if later needed. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 6 ++-- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 28 ++++--------------- + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 2 +- + 3 files changed, 10 insertions(+), 26 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -734,13 +734,13 @@ static irqreturn_t cfe_isr(int irq, void + { + struct cfe_device *cfe = dev; + unsigned int i; +- bool sof[NUM_NODES] = {0}, eof[NUM_NODES] = {0}, lci[NUM_NODES] = {0}; ++ bool sof[NUM_NODES] = {0}, eof[NUM_NODES] = {0}; + u32 sts; + + sts = cfg_reg_read(cfe, MIPICFG_INTS); + + if (sts & MIPICFG_INT_CSI_DMA) +- csi2_isr(&cfe->csi2, sof, eof, lci); ++ csi2_isr(&cfe->csi2, sof, eof); + + if (sts & MIPICFG_INT_PISP_FE) + pisp_fe_isr(&cfe->fe, sof + CSI2_NUM_CHANNELS, +@@ -757,7 +757,7 @@ static irqreturn_t cfe_isr(int irq, void + * generate interrupts even though the node is not streaming. + */ + if (!check_state(cfe, NODE_STREAMING, i) || +- !(sof[i] || eof[i] || lci[i])) ++ !(sof[i] || eof[i])) + continue; + + /* +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -258,7 +258,7 @@ static void csi2_isr_handle_errors(struc + spin_unlock(&csi2->errors_lock); + } + +-void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci) ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof) + { + unsigned int i; + u32 status; +@@ -290,7 +290,6 @@ void csi2_isr(struct csi2_device *csi2, + + sof[i] = !!(status & IRQ_FS(i)); + eof[i] = !!(status & IRQ_FE_ACK(i)); +- lci[i] = !!(status & IRQ_LE_ACK(i)); + } + + if (csi2_track_errors) +@@ -405,16 +404,12 @@ void csi2_start_channel(struct csi2_devi + + csi2_dbg("%s [%u]\n", __func__, channel); + +- /* +- * Disable the channel, but ensure N != 0! Otherwise we end up with a +- * spurious LE + LE_ACK interrupt when re-enabling the channel. +- */ +- csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0x100 << __ffs(LC_MASK)); ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0); + csi2_reg_write(csi2, CSI2_CH_DEBUG(channel), 0); + csi2_reg_write(csi2, CSI2_STATUS, IRQ_CH_MASK(channel)); + +- /* Enable channel and FS/FE/LE interrupts. */ +- ctrl = DMA_EN | IRQ_EN_FS | IRQ_EN_FE_ACK | IRQ_EN_LE_ACK | PACK_LINE; ++ /* Enable channel and FS/FE interrupts. */ ++ ctrl = DMA_EN | IRQ_EN_FS | IRQ_EN_FE_ACK | PACK_LINE; + /* PACK_BYTES ensures no striding for embedded data. */ + if (pack_bytes) + ctrl |= PACK_BYTES; +@@ -423,21 +418,11 @@ void csi2_start_channel(struct csi2_devi + ctrl |= AUTO_ARM; + + if (width && height) { +- int line_int_freq = height >> 2; +- +- line_int_freq = min(max(0x80, line_int_freq), 0x3ff); +- set_field(&ctrl, line_int_freq, LC_MASK); + set_field(&ctrl, mode, CH_MODE_MASK); + csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), + (height << 16) | width); + } else { +- /* +- * Do not disable line interrupts for the embedded data channel, +- * set it to the maximum value. This avoids spamming the ISR +- * with spurious line interrupts. +- */ +- set_field(&ctrl, 0x3ff, LC_MASK); +- set_field(&ctrl, 0x00, CH_MODE_MASK); ++ set_field(&ctrl, 0x0, CH_MODE_MASK); + csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0); + } + +@@ -452,8 +437,7 @@ void csi2_stop_channel(struct csi2_devic + csi2_dbg("%s [%u]\n", __func__, channel); + + /* Channel disable. Use FORCE to allow stopping mid-frame. */ +- csi2_reg_write(csi2, CSI2_CH_CTRL(channel), +- (0x100 << __ffs(LC_MASK)) | FORCE); ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), FORCE); + /* Latch the above change by writing to the ADDR0 register. */ + csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0); + /* Write this again, the HW needs it! */ +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -71,7 +71,7 @@ struct csi2_device { + u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES]; + }; + +-void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci); ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof); + void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, + dma_addr_t dmaaddr, unsigned int stride, + unsigned int size); diff --git a/target/linux/bcm27xx/patches-6.1/950-1210-media-rp1-csi2-Use-standard-link_validate.patch b/target/linux/bcm27xx/patches-6.1/950-1210-media-rp1-csi2-Use-standard-link_validate.patch new file mode 100644 index 0000000000..a3836150dc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1210-media-rp1-csi2-Use-standard-link_validate.patch @@ -0,0 +1,75 @@ +From b6316a8450d3cb99b7599175d59b1b7f710770f5 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 3 Oct 2023 13:59:02 +0300 +Subject: [PATCH] media: rp1: csi2: Use standard link_validate + +The current csi2_link_validate() skips some important checks. Let's +rather use the standard v4l2_subdev_link_validate_default() as the +link_validate hook. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 41 +------------------ + 1 file changed, 1 insertion(+), 40 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -462,11 +462,6 @@ void csi2_close_rx(struct csi2_device *c + csi2_reg_write(csi2, CSI2_IRQ_MASK, 0); + } + +-static struct csi2_device *to_csi2_device(struct v4l2_subdev *subdev) +-{ +- return container_of(subdev, struct csi2_device, sd); +-} +- + static int csi2_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) + { +@@ -554,45 +549,11 @@ static int csi2_pad_set_fmt(struct v4l2_ + return 0; + } + +-static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link, +- struct v4l2_subdev_format *source_fmt, +- struct v4l2_subdev_format *sink_fmt) +-{ +- struct csi2_device *csi2 = to_csi2_device(sd); +- +- csi2_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, +- link->source->entity->name, link->source->index, +- link->sink->entity->name, link->sink->index); +- +- if ((link->source->entity == &csi2->sd.entity && +- link->source->index == 1) || +- (link->sink->entity == &csi2->sd.entity && +- link->sink->index == 1)) { +- csi2_dbg("Ignore metadata pad for now\n"); +- return 0; +- } +- +- /* The width, height and code must match. */ +- if (source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.code != sink_fmt->format.code) { +- csi2_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", +- __func__, +- source_fmt->format.width, source_fmt->format.height, +- source_fmt->format.code, +- sink_fmt->format.width, sink_fmt->format.height, +- sink_fmt->format.code); +- return -EPIPE; +- } +- +- return 0; +-} +- + static const struct v4l2_subdev_pad_ops csi2_subdev_pad_ops = { + .init_cfg = csi2_init_cfg, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = csi2_pad_set_fmt, +- .link_validate = csi2_link_validate, ++ .link_validate = v4l2_subdev_link_validate_default, + }; + + static const struct media_entity_operations csi2_entity_ops = { diff --git a/target/linux/bcm27xx/patches-6.1/950-1211-media-rp1-fe-Use-standard-link_validate.patch b/target/linux/bcm27xx/patches-6.1/950-1211-media-rp1-fe-Use-standard-link_validate.patch new file mode 100644 index 0000000000..d36ea5bd52 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1211-media-rp1-fe-Use-standard-link_validate.patch @@ -0,0 +1,70 @@ +From 0eeb351222adbc5b534c86f7815ee787babc3485 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 3 Oct 2023 14:34:43 +0300 +Subject: [PATCH] media: rp1: fe: Use standard link_validate + +The current pisp_fe_link_validate() skips some important checks. Let's +rather use the standard v4l2_subdev_link_validate_default() as the +link_validate hook. + +Signed-off-by: Tomi Valkeinen +--- + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 36 +------------------ + 1 file changed, 1 insertion(+), 35 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -388,11 +388,6 @@ void pisp_fe_stop(struct pisp_fe_device + pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); + } + +-static struct pisp_fe_device *to_pisp_fe_device(struct v4l2_subdev *subdev) +-{ +- return container_of(subdev, struct pisp_fe_device, sd); +-} +- + static int pisp_fe_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) + { +@@ -492,40 +487,11 @@ static int pisp_fe_pad_set_fmt(struct v4 + } + } + +-static int pisp_fe_link_validate(struct v4l2_subdev *sd, +- struct media_link *link, +- struct v4l2_subdev_format *source_fmt, +- struct v4l2_subdev_format *sink_fmt) +-{ +- struct pisp_fe_device *fe = to_pisp_fe_device(sd); +- +- pisp_fe_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, +- link->source->entity->name, link->source->index, +- link->sink->entity->name, link->sink->index); +- +- /* The width, height and code must match. */ +- if (source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.code != sink_fmt->format.code) { +- pisp_fe_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", +- __func__, +- source_fmt->format.width, +- source_fmt->format.height, +- source_fmt->format.code, +- sink_fmt->format.width, +- sink_fmt->format.height, +- sink_fmt->format.code); +- return -EPIPE; +- } +- +- return 0; +-} +- + static const struct v4l2_subdev_pad_ops pisp_fe_subdev_pad_ops = { + .init_cfg = pisp_fe_init_cfg, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = pisp_fe_pad_set_fmt, +- .link_validate = pisp_fe_link_validate, ++ .link_validate = v4l2_subdev_link_validate_default, + }; + + static const struct media_entity_operations pisp_fe_entity_ops = { diff --git a/target/linux/bcm27xx/patches-6.1/950-1212-media-rp1-cfe-Improve-link-validation-for-metadata.patch b/target/linux/bcm27xx/patches-6.1/950-1212-media-rp1-cfe-Improve-link-validation-for-metadata.patch new file mode 100644 index 0000000000..d85a90aac1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1212-media-rp1-cfe-Improve-link-validation-for-metadata.patch @@ -0,0 +1,61 @@ +From e0f52ccfe1e383622fb30708acd38921e84fbff4 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 3 Oct 2023 14:29:44 +0300 +Subject: [PATCH] media: rp1: cfe: Improve link validation for metadata + +Improve the link validation for metadata by: +- Allowing capture buffers that are larger than the incoming frame + (instead of requiring exact match). + +- Instead of assuming that a metadata unit ("pixel") is 8 bits, use + find_format_by_code() to get the format and use the bit depth from + there. E.g. bit depth for RAW10 metadata will be 10 bits, when we + move to the upstream metadata formats. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 32 +++++++++++++------ + 1 file changed, 22 insertions(+), 10 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -1715,17 +1715,29 @@ static int cfe_video_link_validate(struc + } + } else if (is_csi2_node(node) && is_meta_output_node(node)) { + struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta; ++ const struct cfe_fmt *fmt; ++ u32 source_size; + +- if (source_fmt->width * source_fmt->height != +- meta_fmt->buffersize || +- source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) { +- cfe_err("WARNING: Wrong metadata width/height/code %ux%u %08x (remote pad set to %ux%u %08x)\n", +- meta_fmt->buffersize, 1, +- MEDIA_BUS_FMT_SENSOR_DATA, +- source_fmt->width, +- source_fmt->height, +- source_fmt->code); +- /* TODO: this should throw an error eventually */ ++ fmt = find_format_by_code(source_fmt->code); ++ if (!fmt || fmt->fourcc != meta_fmt->dataformat) { ++ cfe_err("Metadata format mismatch!\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ source_size = DIV_ROUND_UP(source_fmt->width * source_fmt->height * fmt->depth, 8); ++ ++ if (source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) { ++ cfe_err("Bad metadata mbus format\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (source_size > meta_fmt->buffersize) { ++ cfe_err("Metadata buffer too small: %u < %u\n", ++ meta_fmt->buffersize, source_size); ++ ret = -EINVAL; ++ goto out; + } + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1214-drivers-pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch b/target/linux/bcm27xx/patches-6.1/950-1214-drivers-pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch new file mode 100644 index 0000000000..c3e4140fa2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1214-drivers-pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch @@ -0,0 +1,24 @@ +From 046d03c87ecce5db074eae6ffa2d5298c5f7d5a7 Mon Sep 17 00:00:00 2001 +From: Leon Anavi +Date: Tue, 12 Dec 2023 13:53:37 +0200 +Subject: [PATCH] drivers/pinctrl/bcm/Kconfig: Fix BCM2712 help + +Replace "Broadcom BCM2835 GPIO" with "Broadcom BCM2712 PINCONF" +in the help message. This work was sponsored by GOVCERT.LU. + +Signed-off-by: Leon Anavi +--- + drivers/pinctrl/bcm/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pinctrl/bcm/Kconfig ++++ b/drivers/pinctrl/bcm/Kconfig +@@ -10,7 +10,7 @@ config PINCTRL_BCM2712 + select PINCONF + select GENERIC_PINCONF + help +- Say Y here to enable the Broadcom BCM2835 GPIO driver. ++ Say Y here to enable the Broadcom BCM2712 PINCONF driver. + + config PINCTRL_BCM281XX + bool "Broadcom BCM281xx pinctrl driver" diff --git a/target/linux/bcm27xx/patches-6.1/950-1216-drivers-gpu-drm-panel-fix-waveshare-panel-software-r.patch b/target/linux/bcm27xx/patches-6.1/950-1216-drivers-gpu-drm-panel-fix-waveshare-panel-software-r.patch new file mode 100644 index 0000000000..aeb63589fc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1216-drivers-gpu-drm-panel-fix-waveshare-panel-software-r.patch @@ -0,0 +1,41 @@ +From a6872b25f18fe46ef9979f9d4a3635a9c3966afd Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Mon, 11 Dec 2023 15:06:45 +0800 +Subject: [PATCH] drivers/gpu/drm/panel:fix waveshare panel software + restart/shutdown display is abnormal Fixed the screen stays white when the + user restarts or shuts down + +Signed-off-by: eng33 +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -362,9 +362,18 @@ static void ws_panel_remove(struct i2c_c + { + struct ws_panel *ts = i2c_get_clientdata(i2c); + ++ ws_panel_disable(&ts->base); ++ + drm_panel_remove(&ts->base); + } + ++static void ws_panel_shutdown(struct i2c_client *i2c) ++{ ++ struct ws_panel *ts = i2c_get_clientdata(i2c); ++ ++ ws_panel_disable(&ts->base); ++} ++ + static const struct of_device_id ws_panel_of_ids[] = { + { + .compatible = "waveshare,2.8inch-panel", +@@ -403,6 +412,7 @@ static struct i2c_driver ws_panel_driver + }, + .probe = ws_panel_probe, + .remove = ws_panel_remove, ++ .shutdown = ws_panel_shutdown, + }; + module_i2c_driver(ws_panel_driver); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1217-firmware-psci-Pass-given-partition-number-through.patch b/target/linux/bcm27xx/patches-6.1/950-1217-firmware-psci-Pass-given-partition-number-through.patch new file mode 100644 index 0000000000..7feeb224d1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1217-firmware-psci-Pass-given-partition-number-through.patch @@ -0,0 +1,33 @@ +From 6988ae7c909dc342322a82daaa3a95b78d038305 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 11 Dec 2023 16:58:07 +0000 +Subject: [PATCH] firmware/psci: Pass given partition number through + +Pi 5 uses BL31 as its armstub file, so the reset goes via PSCI. Parse +any "reboot" parameter as a partition number to reboot into. +N.B. This code path is only used if reboot mode has been set to warm +or soft. + +Signed-off-by: Phil Elwell +--- + drivers/firmware/psci/psci.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/firmware/psci/psci.c ++++ b/drivers/firmware/psci/psci.c +@@ -314,7 +314,14 @@ static int psci_sys_reset(struct notifie + * reset_type[30:0] = 0 (SYSTEM_WARM_RESET) + * cookie = 0 (ignored by the implementation) + */ +- invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, 0, 0); ++ // Allow extra arguments separated by spaces after ++ // the partition number. ++ unsigned long val; ++ u8 partition = 0; ++ ++ if (data && sscanf(data, "%lu", &val) == 1 && val < 63) ++ partition = val; ++ invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, partition, 0); + } else { + invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-1218-dts-bcm2712-rpi-5-b-Enable-warm-reboot-mode.patch b/target/linux/bcm27xx/patches-6.1/950-1218-dts-bcm2712-rpi-5-b-Enable-warm-reboot-mode.patch new file mode 100644 index 0000000000..8bcf587e6d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1218-dts-bcm2712-rpi-5-b-Enable-warm-reboot-mode.patch @@ -0,0 +1,23 @@ +From 5d87d7f91cb4f1d0f391f6fe9dd0524b363b78e3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 11 Dec 2023 17:00:56 +0000 +Subject: [PATCH] dts: bcm2712-rpi-5-b: Enable warm reboot mode + +Switch to warm reboot mode so that the partition number is preserved. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -428,7 +428,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_g + + / { + chosen: chosen { +- bootargs = "coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; ++ bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + stdout-path = "serial10:115200n8"; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1222-drivers-media-i2c-imx296-imx477-Configure-tigger_mod.patch b/target/linux/bcm27xx/patches-6.1/950-1222-drivers-media-i2c-imx296-imx477-Configure-tigger_mod.patch new file mode 100644 index 0000000000..be1eb5611e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1222-drivers-media-i2c-imx296-imx477-Configure-tigger_mod.patch @@ -0,0 +1,85 @@ +From 083f39e40d980b47ab12b451d40b9f935bb22a5b Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 6 Dec 2023 14:27:57 +0000 +Subject: [PATCH] drivers: media: i2c: imx296,imx477: Configure tigger_mode + every time + +Don't assume the camera has been reset each time we start streaming, +but always write registers relating to trigger_mode, even in mode 0. + +IMX477: Stop driving XVS on stop streaming, to avoid spurious pulses. + +Signed-off-by: Nick Hollinghurst +--- + drivers/media/i2c/imx296.c | 9 +++++---- + drivers/media/i2c/imx477.c | 29 ++++++++++++++--------------- + 2 files changed, 19 insertions(+), 19 deletions(-) + +--- a/drivers/media/i2c/imx296.c ++++ b/drivers/media/i2c/imx296.c +@@ -650,10 +650,11 @@ static int imx296_stream_on(struct imx29 + imx296_write(sensor, IMX296_CTRL00, 0, &ret); + usleep_range(2000, 5000); + +- if (trigger_mode == 1) { +- imx296_write(sensor, IMX296_CTRL0B, IMX296_CTRL0B_TRIGEN, &ret); +- imx296_write(sensor, IMX296_LOWLAGTRG, IMX296_LOWLAGTRG_FAST, &ret); +- } ++ /* external trigger mode: 0=normal, 1=triggered */ ++ imx296_write(sensor, IMX296_CTRL0B, ++ (trigger_mode == 1) ? IMX296_CTRL0B_TRIGEN : 0, &ret); ++ imx296_write(sensor, IMX296_LOWLAGTRG, ++ (trigger_mode == 1) ? IMX296_LOWLAGTRG_FAST : 0, &ret); + + imx296_write(sensor, IMX296_CTRL0A, 0, &ret); + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -1742,26 +1742,21 @@ static int imx477_start_streaming(struct + imx477_write_reg(imx477, 0x0b05, IMX477_REG_VALUE_08BIT, !!dpc_enable); + imx477_write_reg(imx477, 0x0b06, IMX477_REG_VALUE_08BIT, !!dpc_enable); + +- /* Set vsync trigger mode */ +- if (trigger_mode != 0) { +- /* trigger_mode == 1 for source, 2 for sink */ +- const u32 val = (trigger_mode == 1) ? 1 : 0; +- +- imx477_write_reg(imx477, IMX477_REG_MC_MODE, +- IMX477_REG_VALUE_08BIT, 1); +- imx477_write_reg(imx477, IMX477_REG_MS_SEL, +- IMX477_REG_VALUE_08BIT, val); +- imx477_write_reg(imx477, IMX477_REG_XVS_IO_CTRL, +- IMX477_REG_VALUE_08BIT, val); +- imx477_write_reg(imx477, IMX477_REG_EXTOUT_EN, +- IMX477_REG_VALUE_08BIT, val); +- } +- + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx477->sd.ctrl_handler); + if (ret) + return ret; + ++ /* Set vsync trigger mode: 0=standalone, 1=source, 2=sink */ ++ imx477_write_reg(imx477, IMX477_REG_MC_MODE, ++ IMX477_REG_VALUE_08BIT, (trigger_mode > 0) ? 1 : 0); ++ imx477_write_reg(imx477, IMX477_REG_MS_SEL, ++ IMX477_REG_VALUE_08BIT, (trigger_mode <= 1) ? 1 : 0); ++ imx477_write_reg(imx477, IMX477_REG_XVS_IO_CTRL, ++ IMX477_REG_VALUE_08BIT, (trigger_mode == 1) ? 1 : 0); ++ imx477_write_reg(imx477, IMX477_REG_EXTOUT_EN, ++ IMX477_REG_VALUE_08BIT, (trigger_mode == 1) ? 1 : 0); ++ + /* set stream on register */ + return imx477_write_reg(imx477, IMX477_REG_MODE_SELECT, + IMX477_REG_VALUE_08BIT, IMX477_MODE_STREAMING); +@@ -1778,6 +1773,10 @@ static void imx477_stop_streaming(struct + IMX477_REG_VALUE_08BIT, IMX477_MODE_STANDBY); + if (ret) + dev_err(&client->dev, "%s failed to set stream\n", __func__); ++ ++ /* Stop driving XVS out (there is still a weak pull-up) */ ++ imx477_write_reg(imx477, IMX477_REG_EXTOUT_EN, ++ IMX477_REG_VALUE_08BIT, 0); + } + + static int imx477_set_stream(struct v4l2_subdev *sd, int enable) diff --git a/target/linux/bcm27xx/patches-6.1/950-1223-overlays-Add-always-on-parameter-to-imx477-and-imx29.patch b/target/linux/bcm27xx/patches-6.1/950-1223-overlays-Add-always-on-parameter-to-imx477-and-imx29.patch new file mode 100644 index 0000000000..d705df6f40 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1223-overlays-Add-always-on-parameter-to-imx477-and-imx29.patch @@ -0,0 +1,99 @@ +From 3ed57f25f3074f6abfe570fc11aa7d370fdc499a Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 6 Dec 2023 14:38:03 +0000 +Subject: [PATCH] overlays: Add "always-on" parameter to imx477 and imx296 + +Leave the camera's power supplies up, to prevent the camera +clamping its 1.8V digital I/Os to ground. This may be useful +when synchronizing multiple camera systems using XVS or XTRIG. + +Signed-off-by: Nick Hollinghurst +--- + arch/arm/boot/dts/overlays/README | 6 ++++++ + arch/arm/boot/dts/overlays/imx296-overlay.dts | 9 +++++++++ + arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi | 9 +++++++++ + 3 files changed, 24 insertions(+) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2520,6 +2520,8 @@ Params: rotation Mounting + clock-frequency Sets the clock frequency to match that used on + the board, which should be one of 54000000 + (the default), 37125000 or 74250000. ++ always-on Leave the regulator powered up, to stop the ++ camera clamping I/Os such as XTRIG to 0V. + + + Name: imx327 +@@ -2558,6 +2560,8 @@ Params: rotation Mounting + configuring the sensor (default on) + cam0 Adopt the default configuration for CAM0 on a + Compute Module (CSI0, i2c_vc, and cam0_reg). ++ always-on Leave the regulator powered up, to stop the ++ camera clamping I/Os such as XVS to 0V. + + + Name: imx462 +@@ -2596,6 +2600,8 @@ Params: rotation Mounting + configuring the sensor (default on) + cam0 Adopt the default configuration for CAM0 on a + Compute Module (CSI0, i2c_vc, and cam0_reg). ++ always-on Leave the regulator powered up, to stop the ++ camera clamping I/Os such as XVS to 0V. + + + Name: imx519 +--- a/arch/arm/boot/dts/overlays/imx296-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx296-overlay.dts +@@ -37,6 +37,13 @@ + }; + }; + ++ reg_alwayson_frag: fragment@99 { ++ target = <&cam1_reg>; ++ __dormant__ { ++ regulator-always-on; ++ }; ++ }; ++ + i2c_frag: fragment@100 { + target = <&i2c_csi_dsi>; + __overlay__ { +@@ -98,8 +105,10 @@ + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, ++ <®_alwayson_frag>, "target:0=",<&cam0_reg>, + <&imx296>, "clocks:0=",<&cam0_clk>, + <&imx296>, "avdd-supply:0=",<&cam0_reg>; + clock-frequency = <&clk_over>, "clock-frequency:0"; ++ always-on = <0>, "+99"; + }; + }; +--- a/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi +@@ -33,6 +33,13 @@ + }; + }; + ++ reg_alwayson_frag: fragment@99 { ++ target = <&cam1_reg>; ++ __dormant__ { ++ regulator-always-on; ++ }; ++ }; ++ + i2c_frag: fragment@100 { + target = <&i2c_csi_dsi>; + __overlay__ { +@@ -69,8 +76,10 @@ + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, ++ <®_alwayson_frag>, "target:0=",<&cam0_reg>, + <&cam_node>, "clocks:0=",<&cam0_clk>, + <&cam_node>, "VANA-supply:0=",<&cam0_reg>; ++ always-on = <0>, "+99"; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1224-input-edt-ft5x06-Correct-prefix-length-in-snprintf.patch b/target/linux/bcm27xx/patches-6.1/950-1224-input-edt-ft5x06-Correct-prefix-length-in-snprintf.patch new file mode 100644 index 0000000000..6fb8fc0b95 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1224-input-edt-ft5x06-Correct-prefix-length-in-snprintf.patch @@ -0,0 +1,29 @@ +From e0ecfaf1abfd5ef63ceec7606352020a80a2742b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 18 Dec 2023 11:49:36 +0000 +Subject: [PATCH] input: edt-ft5x06: Correct prefix length in snprintf + +snprintf takes the length of the array that we can print into, +and has to fit the NULL terminator in there too. +Printing the prefix is generally "12-3456 " which is 8 desired +characters (the length of EDT_NAME_PREFIX_LEN) and the NULL. +The space is therefore being truncated to fit the NULL in. + +Increase the length snprintf is allowed to use. + +Signed-off-by: Dave Stevenson +--- + drivers/input/touchscreen/edt-ft5x06.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -966,7 +966,7 @@ static int edt_ft5x06_ts_identify(struct + char *model_name = tsdata->name; + char *fw_version = tsdata->fw_version; + +- snprintf(model_name, EDT_NAME_PREFIX_LEN, "%s ", dev_name(&client->dev)); ++ snprintf(model_name, EDT_NAME_PREFIX_LEN + 1, "%s ", dev_name(&client->dev)); + model_name += strlen(model_name); + + /* see what we find if we assume it is a M06 * diff --git a/target/linux/bcm27xx/patches-6.1/950-1225-ARM-dts-bcm2712-rpi-5-b-Allow-RTC-to-be-disabled.patch b/target/linux/bcm27xx/patches-6.1/950-1225-ARM-dts-bcm2712-rpi-5-b-Allow-RTC-to-be-disabled.patch new file mode 100644 index 0000000000..5a3e6df555 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1225-ARM-dts-bcm2712-rpi-5-b-Allow-RTC-to-be-disabled.patch @@ -0,0 +1,38 @@ +From da5fd98469edd797ed77d9a8690a608c6b54f9e6 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Dec 2023 14:55:21 +0000 +Subject: [PATCH] ARM: dts: bcm2712-rpi-5-b: Allow RTC to be disabled + +Add a dtparam "rtc", so that "dtparam=rtc=off" can be used to disable +the Pi 5's onboard RTC. + +See: https://forums.raspberrypi.com/viewtopic.php?t=361813 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 1 + + arch/arm/boot/dts/overlays/README | 3 +++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -819,6 +819,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + 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"; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -307,6 +307,9 @@ Params: + random Set to "on" to enable the hardware random + number generator (default "on") + ++ rtc Set to "off" to disable the onboard Real Time ++ Clock (2712 only, default "on") ++ + rtc_bbat_vchg Set the RTC backup battery charging voltage in + microvolts. If set to 0 or not specified, the + trickle charger is disabled. diff --git a/target/linux/bcm27xx/patches-6.1/950-1226-i2c-designware-Look-for-CNT-values-in-DT.patch b/target/linux/bcm27xx/patches-6.1/950-1226-i2c-designware-Look-for-CNT-values-in-DT.patch new file mode 100644 index 0000000000..ccba16ad8e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1226-i2c-designware-Look-for-CNT-values-in-DT.patch @@ -0,0 +1,57 @@ +From 0a09088e24c013ef608b1bb79501ef890cefc767 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Dec 2023 11:16:25 +0000 +Subject: [PATCH] i2c: designware: Look for *CNT values in DT + +The i2c-designware driver supports reading precise timing values from +ACPI, but the Device Tree support relies on a combination of standard +rise and fall times and hard-coded minimum timings. The result of this +is that it is difficult to get optimum timings, particularly given that +the values are bus speed-specific and only one set can be stored in +DT at a time. + +Add support for initialisation from DT that is similar to that for +ACPI. + +Signed-off-by: Phil Elwell +--- + drivers/i2c/busses/i2c-designware-platdrv.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/i2c/busses/i2c-designware-platdrv.c ++++ b/drivers/i2c/busses/i2c-designware-platdrv.c +@@ -132,9 +132,18 @@ static int mscc_twi_set_sda_hold_time(st + return 0; + } + ++static void dw_i2c_read_of_cnt(struct device_node *np, const char *name, u16 *pval) ++{ ++ u32 val; ++ ++ if (!of_property_read_u32(np, name, &val)) ++ *pval = (u16)val; ++} ++ + static int dw_i2c_of_configure(struct platform_device *pdev) + { + struct dw_i2c_dev *dev = platform_get_drvdata(pdev); ++ struct device_node *np = pdev->dev.of_node; + + switch (dev->flags & MODEL_MASK) { + case MODEL_MSCC_OCELOT: +@@ -146,6 +155,15 @@ static int dw_i2c_of_configure(struct pl + break; + } + ++ dw_i2c_read_of_cnt(np, "snps,ss_hcnt", &dev->ss_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,ss_lcnt", &dev->ss_lcnt); ++ dw_i2c_read_of_cnt(np, "snps,fs_hcnt", &dev->fs_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,fs_lcnt", &dev->fs_lcnt); ++ dw_i2c_read_of_cnt(np, "snps,fp_hcnt", &dev->fp_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,fp_lcnt", &dev->fp_lcnt); ++ dw_i2c_read_of_cnt(np, "snps,hs_hcnt", &dev->hs_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,hs_lcnt", &dev->hs_lcnt); ++ + return 0; + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1227-dts-rp1-Add-I2C-timings.patch b/target/linux/bcm27xx/patches-6.1/950-1227-dts-rp1-Add-I2C-timings.patch new file mode 100644 index 0000000000..892f31ec9f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1227-dts-rp1-Add-I2C-timings.patch @@ -0,0 +1,103 @@ +From 660d569b1a623e4b64350e608bbf8bc2cc6332e9 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Dec 2023 11:27:20 +0000 +Subject: [PATCH] dts: rp1: Add I2C timings + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/rp1.dtsi | 42 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +--- a/arch/arm/boot/dts/rp1.dtsi ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -305,6 +305,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -313,6 +319,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -321,6 +333,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -329,6 +347,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -337,6 +361,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -345,6 +375,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -353,6 +389,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1228-drivers-media-pisp_be-pisp_fe-Update-UAPI-header-lic.patch b/target/linux/bcm27xx/patches-6.1/950-1228-drivers-media-pisp_be-pisp_fe-Update-UAPI-header-lic.patch new file mode 100644 index 0000000000..fc77e4d1cf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1228-drivers-media-pisp_be-pisp_fe-Update-UAPI-header-lic.patch @@ -0,0 +1,58 @@ +From 74c6c159c2b499bdf3c39961bd40eb9243624226 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 29 Nov 2023 13:09:05 +0000 +Subject: [PATCH] drivers: media: pisp_be: pisp_fe: Update UAPI header licenses + +Update the license tags on the pisp UAPI header files with the +"Linux-syscall-note" clause. Also replace the "GPL-2.0" tag with the +preferred "GPL-2.0-only" tag. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * PiSP Back End configuration definitions. + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP common definitions. + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP Front End Driver Configuration structures + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP Front End statistics definitions + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP Front End image definitions. + * diff --git a/target/linux/bcm27xx/patches-6.1/950-1229-drivers-media-cfe-Add-more-robust-ISR-handlers.patch b/target/linux/bcm27xx/patches-6.1/950-1229-drivers-media-cfe-Add-more-robust-ISR-handlers.patch new file mode 100644 index 0000000000..b79cad417f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1229-drivers-media-cfe-Add-more-robust-ISR-handlers.patch @@ -0,0 +1,207 @@ +From 6fb7a0b4c1dd6cf5b12ec2b2c197dcf8e58cd2b9 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 18 Dec 2023 09:52:45 +0000 +Subject: [PATCH] drivers: media: cfe: Add more robust ISR handlers + +Update the ISR logic to be more robust to sensors in problematic states +where interrupts may start arriving overlapped and/or missing. + +1) Test for cur_frame in the FE handler, and if present, dequeue it in +an error state so that it does not get orphaned. + +2) Move the sequence counter and timestamp variables to the node +structures. This allows the ISR to track channels running ahead when +interrupts arrive unordered. + +3) Add a test to ensure we don't have a spurios (but harmlesS) call to +the FE handler in some circumstances. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 92 ++++++++++--------- + 1 file changed, 49 insertions(+), 43 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -272,6 +272,8 @@ struct cfe_node { + /* Pointer to the parent handle */ + struct cfe_device *cfe; + struct media_pad pad; ++ unsigned int fs_count; ++ u64 ts; + }; + + struct cfe_device { +@@ -311,9 +313,6 @@ struct cfe_device { + struct pisp_fe_device fe; + + int fe_csi2_channel; +- +- unsigned int sequence; +- u64 ts; + }; + + static inline bool is_fe_enabled(struct cfe_device *cfe) +@@ -393,17 +392,6 @@ static bool test_all_nodes(struct cfe_de + return true; + } + +-static void clear_all_nodes(struct cfe_device *cfe, unsigned long precond, +- unsigned long state) +-{ +- unsigned int i; +- +- for (i = 0; i < NUM_NODES; i++) { +- if (check_state(cfe, precond, i)) +- clear_state(cfe, state, i); +- } +-} +- + static int mipi_cfg_regs_show(struct seq_file *s, void *data) + { + struct cfe_device *cfe = s->private; +@@ -656,22 +644,22 @@ static void cfe_prepare_next_job(struct + } + + static void cfe_process_buffer_complete(struct cfe_node *node, +- unsigned int sequence) ++ enum vb2_buffer_state state) + { + struct cfe_device *cfe = node->cfe; + + cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, + node_desc[node->id].name, &node->cur_frm->vb.vb2_buf); + +- node->cur_frm->vb.sequence = sequence; +- vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); ++ node->cur_frm->vb.sequence = node->fs_count - 1; ++ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, state); + } + + static void cfe_queue_event_sof(struct cfe_node *node) + { + struct v4l2_event event = { + .type = V4L2_EVENT_FRAME_SYNC, +- .u.frame_sync.frame_sequence = node->cfe->sequence, ++ .u.frame_sync.frame_sequence = node->fs_count - 1, + }; + + v4l2_event_queue(&node->video_dev, &event); +@@ -680,28 +668,53 @@ static void cfe_queue_event_sof(struct c + static void cfe_sof_isr_handler(struct cfe_node *node) + { + struct cfe_device *cfe = node->cfe; ++ bool matching_fs = true; ++ unsigned int i; + + cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); +- +- node->cur_frm = node->next_frm; +- node->next_frm = NULL; ++ node->fs_count); + + /* +- * If this is the first node to see a frame start, sample the +- * timestamp to use for all frames across all channels. ++ * If the sensor is producing unexpected frame event ordering over a ++ * sustained period of time, guard against the possibility of coming ++ * here and orphaning the cur_frm if it's not been dequeued already. ++ * Unfortunately, there is not enough hardware state to tell if this ++ * may have occurred. + */ +- if (!test_any_node(cfe, NODE_STREAMING | FS_INT)) +- cfe->ts = ktime_get_ns(); ++ if (WARN(node->cur_frm, "%s: [%s] Orphanded frame at seq %u\n", ++ __func__, node_desc[node->id].name, node->fs_count)) ++ cfe_process_buffer_complete(node, VB2_BUF_STATE_ERROR); + +- set_state(cfe, FS_INT, node->id); ++ node->cur_frm = node->next_frm; ++ node->next_frm = NULL; ++ node->fs_count++; + +- /* If all nodes have seen a frame start, we can queue another job. */ +- if (test_all_nodes(cfe, NODE_STREAMING, FS_INT)) ++ node->ts = ktime_get_ns(); ++ for (i = 0; i < NUM_NODES; i++) { ++ if (!check_state(cfe, NODE_STREAMING, i) || i == node->id) ++ continue; ++ /* ++ * This checks if any other node has seen a FS. If yes, use the ++ * same timestamp, eventually across all node buffers. ++ */ ++ if (cfe->node[i].fs_count >= node->fs_count) ++ node->ts = cfe->node[i].ts; ++ /* ++ * This checks if all other node have seen a matching FS. If ++ * yes, we can flag another job to be queued. ++ */ ++ if (matching_fs && cfe->node[i].fs_count != node->fs_count) ++ matching_fs = false; ++ } ++ ++ if (matching_fs) + cfe->job_queued = false; + + if (node->cur_frm) +- node->cur_frm->vb.vb2_buf.timestamp = cfe->ts; ++ node->cur_frm->vb.vb2_buf.timestamp = node->ts; ++ ++ set_state(cfe, FS_INT, node->id); ++ clear_state(cfe, FE_INT, node->id); + + if (is_image_output_node(node)) + cfe_queue_event_sof(node); +@@ -712,22 +725,14 @@ static void cfe_eof_isr_handler(struct c + struct cfe_device *cfe = node->cfe; + + cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); ++ node->fs_count - 1); + + if (node->cur_frm) +- cfe_process_buffer_complete(node, cfe->sequence); ++ cfe_process_buffer_complete(node, VB2_BUF_STATE_DONE); + + node->cur_frm = NULL; + set_state(cfe, FE_INT, node->id); +- +- /* +- * If all nodes have seen a frame end, we can increment +- * the sequence counter now. +- */ +- if (test_all_nodes(cfe, NODE_STREAMING, FE_INT)) { +- cfe->sequence++; +- clear_all_nodes(cfe, NODE_STREAMING, FE_INT | FS_INT); +- } ++ clear_state(cfe, FS_INT, node->id); + } + + static irqreturn_t cfe_isr(int irq, void *dev) +@@ -794,7 +799,8 @@ static irqreturn_t cfe_isr(int irq, void + * frame first before the FS handler for the current + * frame. + */ +- if (check_state(cfe, FS_INT, node->id)) { ++ if (check_state(cfe, FS_INT, node->id) && ++ !check_state(cfe, FE_INT, node->id)) { + cfe_dbg("%s: [%s] Handling missing previous FE interrupt\n", + __func__, node_desc[node->id].name); + cfe_eof_isr_handler(node); +@@ -1131,6 +1137,7 @@ static int cfe_start_streaming(struct vb + + clear_state(cfe, FS_INT | FE_INT, node->id); + set_state(cfe, NODE_STREAMING, node->id); ++ node->fs_count = 0; + cfe_start_channel(node); + + if (!test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { +@@ -1166,7 +1173,6 @@ static int cfe_start_streaming(struct vb + csi2_open_rx(&cfe->csi2); + + cfe_dbg("Starting sensor streaming\n"); +- cfe->sequence = 0; + ret = v4l2_subdev_call(cfe->sensor, video, s_stream, 1); + if (ret < 0) { + cfe_err("stream on failed in subdev\n"); diff --git a/target/linux/bcm27xx/patches-6.1/950-1231-ASoC-dwc-Defer-bclk_ratio-handling-to-hw_params.patch b/target/linux/bcm27xx/patches-6.1/950-1231-ASoC-dwc-Defer-bclk_ratio-handling-to-hw_params.patch new file mode 100644 index 0000000000..c187507545 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1231-ASoC-dwc-Defer-bclk_ratio-handling-to-hw_params.patch @@ -0,0 +1,89 @@ +From dfc04900c40eb14f9364d56e96db2cc3340a1f21 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 3 Jan 2024 14:43:43 +0000 +Subject: [PATCH] ASoC: dwc: Defer bclk_ratio handling to hw_params + +bclk_ratio is only a factor in clock producer mode, and needs to +override the default value of num_channels * sample_size. +Move the bclk_ratio handling into the hw_params method, only latching +the value in set_bclk_ratio, to address both of those matters. + +See: https://github.com/raspberrypi/linux/issues/5817 + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 38 +++++++++++++++++++++----------------- + sound/soc/dwc/local.h | 1 + + 2 files changed, 22 insertions(+), 17 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -263,6 +263,25 @@ static int dw_i2s_hw_params(struct snd_p + return -EINVAL; + } + ++ if ((dev->capability & DW_I2S_MASTER) && dev->bclk_ratio) { ++ switch (dev->bclk_ratio) { ++ case 32: ++ dev->ccr = 0x00; ++ break; ++ ++ case 48: ++ dev->ccr = 0x08; ++ break; ++ ++ case 64: ++ dev->ccr = 0x10; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ } ++ + config->chan_nr = params_channels(params); + + switch (config->chan_nr) { +@@ -436,23 +455,7 @@ static int dw_i2s_set_bclk_ratio(struct + + dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio); + +- switch (ratio) { +- case 32: +- dev->ccr = 0x00; +- break; +- +- case 48: +- dev->ccr = 0x08; +- break; +- +- case 64: +- dev->ccr = 0x10; +- break; +- default: +- return -EINVAL; +- } +- +- i2s_write_reg(dev->i2s_base, CCR, dev->ccr); ++ dev->bclk_ratio = ratio; + + return 0; + } +@@ -746,6 +749,7 @@ static int dw_i2s_probe(struct platform_ + } + } + ++ dev->bclk_ratio = 0; + dev->i2s_reg_comp1 = I2S_COMP_PARAM_1; + dev->i2s_reg_comp2 = I2S_COMP_PARAM_2; + if (pdata) { +--- a/sound/soc/dwc/local.h ++++ b/sound/soc/dwc/local.h +@@ -107,6 +107,7 @@ struct dw_i2s_dev { + unsigned int quirks; + unsigned int i2s_reg_comp1; + unsigned int i2s_reg_comp2; ++ unsigned int bclk_ratio; + struct device *dev; + u32 ccr; + u32 xfer_resolution; diff --git a/target/linux/bcm27xx/patches-6.1/950-1232-drm-vc4-Fix-reading-of-frame-count-on-GEN5-Pi4.patch b/target/linux/bcm27xx/patches-6.1/950-1232-drm-vc4-Fix-reading-of-frame-count-on-GEN5-Pi4.patch new file mode 100644 index 0000000000..4374e24244 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1232-drm-vc4-Fix-reading-of-frame-count-on-GEN5-Pi4.patch @@ -0,0 +1,79 @@ +From d5066442e39dd9bf4ba6431ffb3f99e3d5085d3f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 4 Jan 2024 12:02:43 +0000 +Subject: [PATCH] drm/vc4: Fix reading of frame count on GEN5 / Pi4 + +The frame count values moved within registers DISPSTAT1 and +DISPSTAT2 with GEN5, so update the accessor function to +accommodate that. + +Fixes: b51cd7ad143d ("drm/vc4: hvs: Fix frame count register readout") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 23 +++++++++++++++++++++-- + drivers/gpu/drm/vc4/vc4_regs.h | 6 ++++++ + 2 files changed, 27 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -823,10 +823,28 @@ u8 vc4_hvs_get_fifo_frame_count(struct v + if (!drm_dev_enter(drm, &idx)) + return 0; + +- if (vc4->gen >= VC4_GEN_6) { ++ switch (vc4->gen) { ++ case VC4_GEN_6: + field = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(fifo)), + SCALER6_DISPX_STATUS_FRCNT); +- } else { ++ break; ++ case VC4_GEN_5: ++ switch (fifo) { ++ case 0: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER5_DISPSTAT1_FRCNT0); ++ break; ++ case 1: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER5_DISPSTAT1_FRCNT1); ++ break; ++ case 2: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT2), ++ SCALER5_DISPSTAT2_FRCNT2); ++ break; ++ } ++ break; ++ case VC4_GEN_4: + switch (fifo) { + case 0: + field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), +@@ -841,6 +859,7 @@ u8 vc4_hvs_get_fifo_frame_count(struct v + SCALER_DISPSTAT2_FRCNT2); + break; + } ++ break; + } + + drm_dev_exit(idx); +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -424,6 +424,10 @@ + # define SCALER_DISPSTAT1_FRCNT0_SHIFT 18 + # define SCALER_DISPSTAT1_FRCNT1_MASK VC4_MASK(17, 12) + # define SCALER_DISPSTAT1_FRCNT1_SHIFT 12 ++# define SCALER5_DISPSTAT1_FRCNT0_MASK VC4_MASK(25, 20) ++# define SCALER5_DISPSTAT1_FRCNT0_SHIFT 20 ++# define SCALER5_DISPSTAT1_FRCNT1_MASK VC4_MASK(19, 14) ++# define SCALER5_DISPSTAT1_FRCNT1_SHIFT 14 + + #define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \ + (x) * (SCALER_DISPSTAT1 - \ +@@ -442,6 +446,8 @@ + #define SCALER_DISPSTAT2 0x00000068 + # define SCALER_DISPSTAT2_FRCNT2_MASK VC4_MASK(17, 12) + # define SCALER_DISPSTAT2_FRCNT2_SHIFT 12 ++# define SCALER5_DISPSTAT2_FRCNT2_MASK VC4_MASK(19, 14) ++# define SCALER5_DISPSTAT2_FRCNT2_SHIFT 14 + + #define SCALER_DISPBASE2 0x0000006c + #define SCALER_DISPALPHA2 0x00000070 diff --git a/target/linux/bcm27xx/patches-6.1/950-1233-ARM-dts-bcm2712-rpi-5-b-Add-eth_ledx-parameters.patch b/target/linux/bcm27xx/patches-6.1/950-1233-ARM-dts-bcm2712-rpi-5-b-Add-eth_ledx-parameters.patch new file mode 100644 index 0000000000..f0c6efa362 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1233-ARM-dts-bcm2712-rpi-5-b-Add-eth_ledx-parameters.patch @@ -0,0 +1,56 @@ +From eeb5969ae34df16024f39a77496a44ae94bfab13 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 4 Jan 2024 13:56:39 +0000 +Subject: [PATCH] ARM: dts: bcm2712-rpi-5-b: Add eth_ledx parameters + +Include the dtparams controlling the Ethernet jack LEDs, as used on +other Pis. + +See: https://github.com/raspberrypi/linux/issues/5825 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + arch/arm/boot/dts/overlays/README | 6 +++--- + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -830,6 +830,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + act_led_trigger = <&act_led>, "linux,default-trigger"; + pwr_led_activelow = <&pwr_led>, "gpios:8"; + pwr_led_trigger = <&pwr_led>, "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; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -207,7 +207,7 @@ Params: + 0 means never downshift (default 2). Pi3B+ only. + + eth_led0 Set mode of LED0 - amber on Pi3B+ (default "1"), +- green on Pi4 (default "0"). ++ green on Pi4/5 (default "0"). + The legal values are: + + Pi3B+ +@@ -217,7 +217,7 @@ Params: + 4=link100/1000/activity 5=link10/1000/activity + 6=link10/100/activity 14=off 15=on + +- Pi4 ++ Pi4/5 + + 0=Speed/Activity 1=Speed + 2=Flash activity 3=FDX +@@ -226,7 +226,7 @@ Params: + 8=Link 9=Activity + + eth_led1 Set mode of LED1 - green on Pi3B+ (default "6"), +- amber on Pi4 (default "8"). See eth_led0 for ++ amber on Pi4/5 (default "8"). See eth_led0 for + legal values. + + eth_max_speed Set the maximum speed a link is allowed diff --git a/target/linux/bcm27xx/patches-6.1/950-1234-ARM-dts-bcm2712-rpi-5-b-Add-fan-speed-dtparams.patch b/target/linux/bcm27xx/patches-6.1/950-1234-ARM-dts-bcm2712-rpi-5-b-Add-fan-speed-dtparams.patch new file mode 100644 index 0000000000..da2345fdf7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1234-ARM-dts-bcm2712-rpi-5-b-Add-fan-speed-dtparams.patch @@ -0,0 +1,71 @@ +From 2c085a1ff40521ab89d8f1894757aa83b59b4607 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 4 Jan 2024 12:09:10 +0000 +Subject: [PATCH] ARM: dts: bcm2712-rpi-5-b: Add fan speed dtparams + +Add dtparams for adjusting the Pi 5 cooling fan speeds and temperature +thresholds. + +See: https://github.com/raspberrypi/linux/issues/5820 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 13 +++++++++++++ + arch/arm/boot/dts/overlays/README | 25 +++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -844,5 +844,18 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + 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/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -233,6 +233,31 @@ Params: + to negotiate. Legal values are 10, 100 and + 1000 (default 1000). Pi3B+ only. + ++ fan_temp0 Temperature threshold (in millicelcius) for ++ 1st cooling level (default 50000). Pi5 only. ++ fan_temp0_hyst Temperature hysteresis (in millicelcius) for ++ 1st cooling level (default 5000). Pi5 only. ++ fan_temp0_speed Fan PWM setting for 1st cooling level (0-255, ++ default 75). Pi5 only. ++ fan_temp1 Temperature threshold (in millicelcius) for ++ 2nd cooling level (default 60000). Pi5 only. ++ fan_temp1_hyst Temperature hysteresis (in millicelcius) for ++ 2nd cooling level (default 5000). Pi5 only. ++ fan_temp1_speed Fan PWM setting for 2nd cooling level (0-255, ++ default 125). Pi5 only. ++ fan_temp2 Temperature threshold (in millicelcius) for ++ 3rd cooling level (default 67500). Pi5 only. ++ fan_temp2_hyst Temperature hysteresis (in millicelcius) for ++ 3rd cooling level (default 5000). Pi5 only. ++ fan_temp2_speed Fan PWM setting for 3rd cooling level (0-255, ++ default 175). Pi5 only. ++ fan_temp3 Temperature threshold (in millicelcius) for ++ 4th cooling level (default 75000). Pi5 only. ++ fan_temp3_hyst Temperature hysteresis (in millicelcius) for ++ 4th cooling level (default 5000). Pi5 only. ++ fan_temp3_speed Fan PWM setting for 4th cooling level (0-255, ++ default 250). Pi5 only. ++ + hdmi Set to "off" to disable the HDMI interface + (default "on") + diff --git a/target/linux/bcm27xx/patches-6.1/950-1235-drm-vc4-don-t-check-if-plane-state-fb-state-fb.patch b/target/linux/bcm27xx/patches-6.1/950-1235-drm-vc4-don-t-check-if-plane-state-fb-state-fb.patch new file mode 100644 index 0000000000..7c7c05c5ef --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1235-drm-vc4-don-t-check-if-plane-state-fb-state-fb.patch @@ -0,0 +1,93 @@ +From 146bbf9627f6c37816939de29538ec8ee9a7be1a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ma=C3=ADra=20Canal?= +Date: Fri, 5 Jan 2024 15:07:34 -0300 +Subject: [PATCH] drm/vc4: don't check if plane->state->fb == state->fb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently, when using non-blocking commits, we can see the following +kernel warning: + +[ 110.908514] ------------[ cut here ]------------ +[ 110.908529] refcount_t: underflow; use-after-free. +[ 110.908620] WARNING: CPU: 0 PID: 1866 at lib/refcount.c:87 refcount_dec_not_one+0xb8/0xc0 +[ 110.908664] Modules linked in: rfcomm snd_seq_dummy snd_hrtimer snd_seq snd_seq_device cmac algif_hash aes_arm64 aes_generic algif_skcipher af_alg bnep hid_logitech_hidpp vc4 brcmfmac hci_uart btbcm brcmutil bluetooth snd_soc_hdmi_codec cfg80211 cec drm_display_helper drm_dma_helper drm_kms_helper snd_soc_core snd_compress snd_pcm_dmaengine fb_sys_fops sysimgblt syscopyarea sysfillrect raspberrypi_hwmon ecdh_generic ecc rfkill libaes i2c_bcm2835 binfmt_misc joydev snd_bcm2835(C) bcm2835_codec(C) bcm2835_isp(C) v4l2_mem2mem videobuf2_dma_contig snd_pcm bcm2835_v4l2(C) raspberrypi_gpiomem bcm2835_mmal_vchiq(C) videobuf2_v4l2 snd_timer videobuf2_vmalloc videobuf2_memops videobuf2_common snd videodev vc_sm_cma(C) mc hid_logitech_dj uio_pdrv_genirq uio i2c_dev drm fuse dm_mod drm_panel_orientation_quirks backlight ip_tables x_tables ipv6 +[ 110.909086] CPU: 0 PID: 1866 Comm: kodi.bin Tainted: G C 6.1.66-v8+ #32 +[ 110.909104] Hardware name: Raspberry Pi 3 Model B Rev 1.2 (DT) +[ 110.909114] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 110.909132] pc : refcount_dec_not_one+0xb8/0xc0 +[ 110.909152] lr : refcount_dec_not_one+0xb4/0xc0 +[ 110.909170] sp : ffffffc00913b9c0 +[ 110.909177] x29: ffffffc00913b9c0 x28: 000000556969bbb0 x27: 000000556990df60 +[ 110.909205] x26: 0000000000000002 x25: 0000000000000004 x24: ffffff8004448480 +[ 110.909230] x23: ffffff800570b500 x22: ffffff802e03a7bc x21: ffffffecfca68c78 +[ 110.909257] x20: ffffff8002b42000 x19: ffffff802e03a600 x18: 0000000000000000 +[ 110.909283] x17: 0000000000000011 x16: ffffffffffffffff x15: 0000000000000004 +[ 110.909308] x14: 0000000000000fff x13: ffffffed577e47e0 x12: 0000000000000003 +[ 110.909333] x11: 0000000000000000 x10: 0000000000000027 x9 : c912d0d083728c00 +[ 110.909359] x8 : c912d0d083728c00 x7 : 65646e75203a745f x6 : 746e756f63666572 +[ 110.909384] x5 : ffffffed579f62ee x4 : ffffffed579eb01e x3 : 0000000000000000 +[ 110.909409] x2 : 0000000000000000 x1 : ffffffc00913b750 x0 : 0000000000000001 +[ 110.909434] Call trace: +[ 110.909441] refcount_dec_not_one+0xb8/0xc0 +[ 110.909461] vc4_bo_dec_usecnt+0x4c/0x1b0 [vc4] +[ 110.909903] vc4_cleanup_fb+0x44/0x50 [vc4] +[ 110.910315] drm_atomic_helper_cleanup_planes+0x88/0xa4 [drm_kms_helper] +[ 110.910669] vc4_atomic_commit_tail+0x390/0x9dc [vc4] +[ 110.911079] commit_tail+0xb0/0x164 [drm_kms_helper] +[ 110.911397] drm_atomic_helper_commit+0x1d0/0x1f0 [drm_kms_helper] +[ 110.911716] drm_atomic_commit+0xb0/0xdc [drm] +[ 110.912569] drm_mode_atomic_ioctl+0x348/0x4b8 [drm] +[ 110.913330] drm_ioctl_kernel+0xec/0x15c [drm] +[ 110.914091] drm_ioctl+0x24c/0x3b0 [drm] +[ 110.914850] __arm64_sys_ioctl+0x9c/0xd4 +[ 110.914873] invoke_syscall+0x4c/0x114 +[ 110.914897] el0_svc_common+0xd0/0x118 +[ 110.914917] do_el0_svc+0x38/0xd0 +[ 110.914936] el0_svc+0x30/0x8c +[ 110.914958] el0t_64_sync_handler+0x84/0xf0 +[ 110.914979] el0t_64_sync+0x18c/0x190 +[ 110.914996] ---[ end trace 0000000000000000 ]--- + +This happens because, although `prepare_fb` and `cleanup_fb` are +perfectly balanced, we cannot guarantee consistency in the check +plane->state->fb == state->fb. This means that sometimes we can increase +the refcount in `prepare_fb` and don't decrease it in `cleanup_fb`. The +opposite can also be true. + +In fact, the struct drm_plane .state shouldn't be accessed directly +but instead, the `drm_atomic_get_new_plane_state()` helper function should +be used. So, we could stick to this check, but using +`drm_atomic_get_new_plane_state()`. But actually, this check is not really +needed. We can increase and decrease the refcount symmetrically without +problems. + +This is going to make the code more simple and consistent. + +Signed-off-by: Maíra Canal +--- + drivers/gpu/drm/vc4/vc4_plane.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -2225,9 +2225,6 @@ static int vc4_prepare_fb(struct drm_pla + + drm_gem_plane_helper_prepare_fb(plane, state); + +- if (plane->state->fb == state->fb) +- return 0; +- + return vc4_bo_inc_usecnt(bo); + } + +@@ -2236,7 +2233,7 @@ static void vc4_cleanup_fb(struct drm_pl + { + struct vc4_bo *bo; + +- if (plane->state->fb == state->fb || !state->fb) ++ if (!state->fb) + return; + + bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); diff --git a/target/linux/bcm27xx/patches-6.1/950-1236-spi-bcm2835-Support-spi0-0cs-and-SPI_NO_CS-mode.patch b/target/linux/bcm27xx/patches-6.1/950-1236-spi-bcm2835-Support-spi0-0cs-and-SPI_NO_CS-mode.patch new file mode 100644 index 0000000000..6039363a40 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1236-spi-bcm2835-Support-spi0-0cs-and-SPI_NO_CS-mode.patch @@ -0,0 +1,42 @@ +From 5d9075ed7e73dc6ccebf78710c78f39ddc2dd78e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 8 Jan 2024 11:42:57 +0000 +Subject: [PATCH] spi: bcm2835: Support spi0-0cs and SPI_NO_CS mode + +The forced conversion of native CS lines into software CS lines is done +whether or not the controller has been given any CS lines to use. This +breaks the use of the spi0-0cs overlay to prevent SPI from claiming any +CS lines, particularly with spidev which doesn't pass in the SPI_NO_CS +flag at creation. + +Use the presence of an empty cs-gpios property as an indication that no +CS lines should be used, bypassing the native CS conversion code. + +See: https://github.com/raspberrypi/linux/issues/5835 + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-bcm2835.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -1222,6 +1222,7 @@ static int bcm2835_spi_setup(struct spi_ + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); + struct bcm2835_spidev *slv = spi_get_ctldata(spi); + struct gpio_chip *chip; ++ int len; + int ret; + u32 cs; + +@@ -1287,6 +1288,10 @@ static int bcm2835_spi_setup(struct spi_ + goto err_cleanup; + } + ++ /* Skip forced CS conversion if controller has an empty cs-gpios property */ ++ if (of_find_property(ctlr->dev.of_node, "cs-gpios", &len) && len == 0) ++ return 0; ++ + /* + * Translate native CS to GPIO + * diff --git a/target/linux/bcm27xx/patches-6.1/950-1237-drivers-media-imx519-Add-V4L2_CID_LINK_FREQ-control.patch b/target/linux/bcm27xx/patches-6.1/950-1237-drivers-media-imx519-Add-V4L2_CID_LINK_FREQ-control.patch new file mode 100644 index 0000000000..889ddd77dc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1237-drivers-media-imx519-Add-V4L2_CID_LINK_FREQ-control.patch @@ -0,0 +1,51 @@ +From 55ed8cded4af6530276b26f567601bed868ae8f5 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +Date: Wed, 10 Jan 2024 08:52:54 +0800 +Subject: [PATCH] drivers: media: imx519: Add V4L2_CID_LINK_FREQ control + +Add V4L2_CID_LINK_FREQ as a read-only control with a value of 408 Mhz. +This will be used by the CFE driver to corretly setup the DPHY timing +parameters in the CSI-2 block. + +Signed-off-by: Lee Jackson +--- + drivers/media/i2c/imx519.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/media/i2c/imx519.c ++++ b/drivers/media/i2c/imx519.c +@@ -145,6 +145,10 @@ struct imx519_mode { + struct imx519_reg_list reg_list; + }; + ++static const s64 imx519_link_freq_menu[] = { ++ IMX519_DEFAULT_LINK_FREQ, ++}; ++ + static const struct imx519_reg mode_common_regs[] = { + {0x0100, 0x00}, + {0x0136, 0x18}, +@@ -1819,6 +1823,7 @@ static int imx519_init_controls(struct i + struct v4l2_ctrl_handler *ctrl_hdlr; + struct i2c_client *client = v4l2_get_subdevdata(&imx519->sd); + struct v4l2_fwnode_device_properties props; ++ struct v4l2_ctrl *link_freq; + unsigned int i; + int ret; + +@@ -1837,6 +1842,15 @@ static int imx519_init_controls(struct i + IMX519_PIXEL_RATE, 1, + IMX519_PIXEL_RATE); + ++ /* LINK_FREQ is also read only */ ++ link_freq = ++ v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx519_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ ARRAY_SIZE(imx519_link_freq_menu) - 1, 0, ++ imx519_link_freq_menu); ++ if (link_freq) ++ link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ + /* + * Create the controls here, but mode specific limits are setup + * in the imx519_set_framing_limits() call below. diff --git a/target/linux/bcm27xx/patches-6.1/950-1238-drivers-media-arducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch b/target/linux/bcm27xx/patches-6.1/950-1238-drivers-media-arducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch new file mode 100644 index 0000000000..df353ffc31 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1238-drivers-media-arducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch @@ -0,0 +1,56 @@ +From 5e339e1502c9be0f624398cf774e5880a6d1a677 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +Date: Wed, 10 Jan 2024 09:06:16 +0800 +Subject: [PATCH] drivers: media: arducam_64mp: Add V4L2_CID_LINK_FREQ control + +Add V4L2_CID_LINK_FREQ as a read-only control with a value of 456 Mhz. +This will be used by the CFE driver to corretly setup the DPHY timing +parameters in the CSI-2 block. + +Signed-off-by: Lee Jackson +--- + drivers/media/i2c/arducam_64mp.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/media/i2c/arducam_64mp.c ++++ b/drivers/media/i2c/arducam_64mp.c +@@ -143,6 +143,10 @@ struct arducam_64mp_mode { + struct arducam_64mp_reg_list reg_list; + }; + ++static const s64 arducam_64mp_link_freq_menu[] = { ++ ARDUCAM_64MP_DEFAULT_LINK_FREQ, ++}; ++ + static const struct arducam_64mp_reg mode_common_regs[] = { + {0x0100, 0x00}, + {0x0136, 0x18}, +@@ -2272,9 +2276,11 @@ static int arducam_64mp_init_controls(st + struct v4l2_ctrl_handler *ctrl_hdlr; + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd); + struct v4l2_fwnode_device_properties props; ++ struct v4l2_ctrl *link_freq; + unsigned int i; + int ret; + u8 test_pattern_max; ++ u8 link_freq_max; + + ctrl_hdlr = &arducam_64mp->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16); +@@ -2292,6 +2298,16 @@ static int arducam_64mp_init_controls(st + ARDUCAM_64MP_PIXEL_RATE, 1, + ARDUCAM_64MP_PIXEL_RATE); + ++ /* LINK_FREQ is also read only */ ++ link_freq_max = ARRAY_SIZE(arducam_64mp_link_freq_menu) - 1; ++ link_freq = ++ v4l2_ctrl_new_int_menu(ctrl_hdlr, &arducam_64mp_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ link_freq_max, 0, ++ arducam_64mp_link_freq_menu); ++ if (link_freq) ++ link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ + /* + * Create the controls here, but mode specific limits are setup + * in the arducam_64mp_set_framing_limits() call below. diff --git a/target/linux/bcm27xx/patches-6.1/950-1239-drivers-gpu-drm-panel-Modify-the-DSI-mode-to-fix-the.patch b/target/linux/bcm27xx/patches-6.1/950-1239-drivers-gpu-drm-panel-Modify-the-DSI-mode-to-fix-the.patch new file mode 100644 index 0000000000..e106b0609a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1239-drivers-gpu-drm-panel-Modify-the-DSI-mode-to-fix-the.patch @@ -0,0 +1,25 @@ +From 7af1e18d2e90ec64f7cb78cdb5163b63b9fbb056 Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Wed, 3 Jan 2024 11:45:04 +0800 +Subject: [PATCH] drivers/gpu/drm/panel:Modify the DSI mode to fix the problem + that 7.9inch cannot be displayed + +Signed-off-by: eng33 +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -340,9 +340,8 @@ static int ws_panel_probe(struct i2c_cli + */ + drm_panel_add(&ts->base); + +- ts->dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | +- MIPI_DSI_MODE_VIDEO_SYNC_PULSE | +- MIPI_DSI_MODE_LPM); ++ ts->dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | ++ MIPI_DSI_CLOCK_NON_CONTINUOUS; + ts->dsi->format = MIPI_DSI_FMT_RGB888; + ts->dsi->lanes = 2; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1240-drivers-gpu-drm-panel-Modified-the-timing-of-11.9inc.patch b/target/linux/bcm27xx/patches-6.1/950-1240-drivers-gpu-drm-panel-Modified-the-timing-of-11.9inc.patch new file mode 100644 index 0000000000..0f04b21137 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1240-drivers-gpu-drm-panel-Modified-the-timing-of-11.9inc.patch @@ -0,0 +1,22 @@ +From aec3f9b6058448c54b74349f16b21185148a8c6e Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Wed, 3 Jan 2024 11:46:50 +0800 +Subject: [PATCH] drivers/gpu/drm/panel:Modified the timing of 11.9inch to fix + the issue that 11.9inch was displayed abnormally + +Signed-off-by: eng33 +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -131,7 +131,7 @@ static const struct drm_display_mode ws_ + .hdisplay = 320, + .hsync_start = 320 + 60, + .hsync_end = 320 + 60 + 60, +- .htotal = 320 + 60 + 60 + 120, ++ .htotal = 320 + 60 + 60 + 60, + .vdisplay = 1480, + .vsync_start = 1480 + 60, + .vsync_end = 1480 + 60 + 60, diff --git a/target/linux/bcm27xx/patches-6.1/950-1241-drm-vc4-Add-2712-support-to-vc4_plane_async_set_fb.patch b/target/linux/bcm27xx/patches-6.1/950-1241-drm-vc4-Add-2712-support-to-vc4_plane_async_set_fb.patch new file mode 100644 index 0000000000..c13eb354fb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1241-drm-vc4-Add-2712-support-to-vc4_plane_async_set_fb.patch @@ -0,0 +1,88 @@ +From a14da0fdb0e052a672c269df7f18c9de698bd827 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 4 Jan 2024 15:02:42 +0000 +Subject: [PATCH] drm/vc4: Add 2712 support to vc4_plane_async_set_fb + +vc4_plane_async_set_fb directly overwrites the plane address in +the dlist entry, but hadn't been updated for the GEN6 / 2712 +dlist format, corrupting the address in the process. + +Add support for the 2712 dlist format to the function. + +Fixes: 1ab1fbbb7e76 ("drm/vc4: hvs: Support BCM2712 HVS") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 46 +++++++++++++++++++++++---------- + 1 file changed, 33 insertions(+), 13 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1865,7 +1865,7 @@ static int vc6_plane_mode_set(struct drm + * The UPM buffer will be allocated in + * vc6_plane_allocate_upm(). + */ +- VC4_SET_FIELD(upper_32_bits(paddr) & 0xf, ++ VC4_SET_FIELD(upper_32_bits(paddr) & 0xff, + SCALER6_PTR0_UPPER_ADDR)); + + /* Pointer Word 1 */ +@@ -2068,7 +2068,8 @@ void vc4_plane_async_set_fb(struct drm_p + { + struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); + struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); +- uint32_t addr; ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ dma_addr_t dma_addr = bo->dma_addr + fb->offsets[0]; + int idx; + + if (!drm_dev_enter(plane->dev, &idx)) +@@ -2078,19 +2079,38 @@ void vc4_plane_async_set_fb(struct drm_p + * because this is only called on the primary plane. + */ + WARN_ON_ONCE(plane->state->crtc_x < 0 || plane->state->crtc_y < 0); +- addr = bo->dma_addr + fb->offsets[0]; + +- /* Write the new address into the hardware immediately. The +- * scanout will start from this address as soon as the FIFO +- * needs to refill with pixels. +- */ +- writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); ++ if (vc4->gen == VC4_GEN_6) { ++ u32 value; + +- /* Also update the CPU-side dlist copy, so that any later +- * atomic updates that don't do a new modeset on our plane +- * also use our updated address. +- */ +- vc4_state->dlist[vc4_state->ptr0_offset[0]] = addr; ++ value = vc4_state->dlist[vc4_state->ptr0_offset[0]] & ++ ~SCALER6_PTR0_UPPER_ADDR_MASK; ++ value |= VC4_SET_FIELD(upper_32_bits(dma_addr) & 0xff, ++ SCALER6_PTR0_UPPER_ADDR); ++ ++ writel(value, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = value; ++ ++ value = lower_32_bits(dma_addr); ++ writel(value, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0] + 1]); ++ vc4_state->dlist[vc4_state->ptr0_offset[0] + 1] = value; ++ } else { ++ u32 addr; ++ ++ addr = (u32)dma_addr; ++ ++ /* Write the new address into the hardware immediately. The ++ * scanout will start from this address as soon as the FIFO ++ * needs to refill with pixels. ++ */ ++ writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); ++ ++ /* Also update the CPU-side dlist copy, so that any later ++ * atomic updates that don't do a new modeset on our plane ++ * also use our updated address. ++ */ ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = addr; ++ } + + drm_dev_exit(idx); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-1242-drm-vc4-Fix-atomic_async_check-to-call-the-right-mod.patch b/target/linux/bcm27xx/patches-6.1/950-1242-drm-vc4-Fix-atomic_async_check-to-call-the-right-mod.patch new file mode 100644 index 0000000000..683c4a46ff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1242-drm-vc4-Fix-atomic_async_check-to-call-the-right-mod.patch @@ -0,0 +1,38 @@ +From bfe927647253ab3a86be16320baa1579518c6786 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 17 Jan 2024 17:00:35 +0000 +Subject: [PATCH] drm/vc4: Fix atomic_async_check to call the right mode_set + function + +vc4_plane_atomic_async_check was always calling vc4_plane_mode_set +to validate and generate the dlist for the check. If async_check +decided it had to fall back to a sync commit, then this GEN4/5 +dlist could get used on GEN6. + +Call either vc4_plane_mode_set or vc6_plane_mode_set as appropriate. + +Fixes: 1ab1fbbb7e76 ("drm/vc4: hvs: Support BCM2712 HVS") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -2194,11 +2194,15 @@ static int vc4_plane_atomic_async_check( + { + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct vc4_plane_state *old_vc4_state, *new_vc4_state; + int ret; + u32 i; + +- ret = vc4_plane_mode_set(plane, new_plane_state); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc6_plane_mode_set(plane, new_plane_state); ++ else ++ ret = vc4_plane_mode_set(plane, new_plane_state); + if (ret) + return ret; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1244-drm-rp1-rp1-vec-Allow-non-standard-modes-with-variou.patch b/target/linux/bcm27xx/patches-6.1/950-1244-drm-rp1-rp1-vec-Allow-non-standard-modes-with-variou.patch new file mode 100644 index 0000000000..fb20dfe94d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1244-drm-rp1-rp1-vec-Allow-non-standard-modes-with-variou.patch @@ -0,0 +1,343 @@ +From 04b88e1a8b867b045bc90d997e8e0260b00dbb15 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Thu, 11 Jan 2024 12:13:03 +0000 +Subject: [PATCH] drm: rp1: rp1-vec: Allow non-standard modes with various + crops + +Tweak sync timings in the advertised modelines. + +Accept other, custom modes, provided they fit within the active +area of one of the existing hardware-supported TV modes. + +Instead of always padding symmetrically, try to respect the user's +[hv]sync_start values, allowing the image to be shifted around +the screen (to fine-tune overscan correction). + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c | 66 ++++++++++++--------- + drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c | 74 ++++++++++++++++++------ + 2 files changed, 96 insertions(+), 44 deletions(-) + +--- a/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -208,26 +207,26 @@ static void rp1vec_connector_destroy(str + static const struct drm_display_mode rp1vec_modes[4] = { + { /* Full size 525/60i with Rec.601 pixel rate */ + DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, +- 720, 720 + 14, 720 + 14 + 64, 858, 0, +- 480, 480 + 7, 480 + 7 + 6, 525, 0, ++ 720, 720 + 16, 720 + 16 + 64, 858, 0, ++ 480, 480 + 6, 480 + 6 + 6, 525, 0, + DRM_MODE_FLAG_INTERLACE) + }, + { /* Cropped and horizontally squashed to be TV-safe */ + DRM_MODE("704x432i", DRM_MODE_TYPE_DRIVER, 15429, +- 704, 704 + 72, 704 + 72 + 72, 980, 0, +- 432, 432 + 31, 432 + 31 + 6, 525, 0, ++ 704, 704 + 76, 704 + 76 + 72, 980, 0, ++ 432, 432 + 30, 432 + 30 + 6, 525, 0, + DRM_MODE_FLAG_INTERLACE) + }, + { /* Full size 625/50i with Rec.601 pixel rate */ + DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, + 720, 720 + 20, 720 + 20 + 64, 864, 0, +- 576, 576 + 4, 576 + 4 + 6, 625, 0, ++ 576, 576 + 5, 576 + 5 + 5, 625, 0, + DRM_MODE_FLAG_INTERLACE) + }, + { /* Cropped and squashed, for square(ish) pixels */ + DRM_MODE("704x512i", DRM_MODE_TYPE_DRIVER, 15429, + 704, 704 + 80, 704 + 80 + 72, 987, 0, +- 512, 512 + 36, 512 + 36 + 6, 625, 0, ++ 512, 512 + 37, 512 + 37 + 5, 625, 0, + DRM_MODE_FLAG_INTERLACE) + } + }; +@@ -298,27 +297,42 @@ static enum drm_mode_status rp1vec_mode_ + const struct drm_display_mode *mode) + { + /* +- * Check the mode roughly matches one of our standard modes +- * (optionally half-height and progressive). Ignore H/V sync +- * timings which for interlaced TV are approximate at best. ++ * Check the mode roughly matches something we can generate. ++ * The hardware driver is very prescriptive about pixel clocks, ++ * line and frame durations, but we'll tolerate rounding errors. ++ * Within each hardware mode, allow image size and position to vary ++ * (to fine-tune overscan correction or emulate retro devices). ++ * Don't check sync timings here: the HW driver will sanitize them. + */ +- int i, prog; + +- prog = !(mode->flags & DRM_MODE_FLAG_INTERLACE); +- +- for (i = 0; i < ARRAY_SIZE(rp1vec_modes); i++) { +- const struct drm_display_mode *ref = rp1vec_modes + i; ++ int prog = !(mode->flags & DRM_MODE_FLAG_INTERLACE); ++ int vtotal_full = mode->vtotal << prog; ++ int vdisplay_full = mode->vdisplay << prog; ++ ++ /* Reject very small frames */ ++ if (vtotal_full < 256 || mode->hdisplay < 256) ++ return MODE_BAD; ++ ++ /* Check lines, frame period (ms) and vertical size limit */ ++ if (vtotal_full >= 524 && vtotal_full <= 526 && ++ mode->htotal * vtotal_full > 33 * mode->clock && ++ mode->htotal * vtotal_full < 34 * mode->clock && ++ vdisplay_full <= 480) ++ goto vgood; ++ if (vtotal_full >= 624 && vtotal_full <= 626 && ++ mode->htotal * vtotal_full > 39 * mode->clock && ++ mode->htotal * vtotal_full < 41 * mode->clock && ++ vdisplay_full <= 576) ++ goto vgood; ++ return MODE_BAD; + +- if (mode->hdisplay == ref->hdisplay && +- mode->vdisplay == (ref->vdisplay >> prog) && +- mode->clock + 2 >= ref->clock && +- mode->clock <= ref->clock + 2 && +- mode->htotal + 2 >= ref->htotal && +- mode->htotal <= ref->htotal + 2 && +- mode->vtotal + 2 >= (ref->vtotal >> prog) && +- mode->vtotal <= (ref->vtotal >> prog) + 2) +- return MODE_OK; +- } ++vgood: ++ /* Check pixel rate (kHz) and horizontal size limit */ ++ if (mode->clock == 13500 && mode->hdisplay <= 720) ++ return MODE_OK; ++ if (mode->clock >= 15428 && mode->clock <= 15429 && ++ mode->hdisplay <= 800) ++ return MODE_OK; + return MODE_BAD; + } + +@@ -440,7 +454,7 @@ static int rp1vec_platform_probe(struct + ret = drmm_mode_config_init(drm); + if (ret) + goto err_free_drm; +- drm->mode_config.max_width = 768; ++ drm->mode_config.max_width = 800; + drm->mode_config.max_height = 576; + drm->mode_config.fb_base = 0; + drm->mode_config.preferred_depth = 32; +--- a/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -82,13 +81,13 @@ static const struct rp1vec_ipixfmt my_fo + /* + * Hardware mode descriptions (@ 108 MHz clock rate). + * These rely largely on "canned" register settings. +- * TODO: Port the generating software from FP to integer, +- * or better factorize the differences between modes. + */ + + struct rp1vec_hwmode { +- u16 total_cols; /* active columns, plus padding for filter context */ ++ u16 total_cols; /* max active columns incl. padding and windowing */ + u16 rows_per_field; /* active lines per field (including partial ones) */ ++ u16 ref_hfp; /* nominal (hsync_start - hdisplay) when max width */ ++ u16 ref_vfp; /* nominal (vsync_start - vdisplay) when max height */ + bool interlaced; /* set for interlaced */ + bool first_field_odd; /* set for interlaced and 30fps */ + u32 yuv_scaling; /* three 10-bit fields {Y, U, V} in 2.8 format */ +@@ -103,6 +102,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 240, ++ .ref_hfp = 12, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1071d0cf, +@@ -118,6 +119,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 240, ++ .ref_hfp = 16, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1c131962, +@@ -135,6 +138,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 243, ++ .ref_hfp = 12, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x1071d0cf, +@@ -150,6 +155,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 243, ++ .ref_hfp = 16, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x1c131962, +@@ -170,6 +177,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 288, ++ .ref_hfp = 16, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x11c1f8e0, +@@ -185,6 +194,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 804, + .rows_per_field = 288, ++ .ref_hfp = 24, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1e635d7f, +@@ -202,6 +213,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 288, ++ .ref_hfp = 16, ++ .ref_vfp = 5, + .interlaced = true, + .first_field_odd = false, + .yuv_scaling = 0x11c1f8e0, +@@ -217,6 +230,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 804, + .rows_per_field = 288, ++ .ref_hfp = 24, ++ .ref_vfp = 5, + .interlaced = true, + .first_field_odd = false, + .yuv_scaling = 0x1e635d7f, +@@ -237,6 +252,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 240, ++ .ref_hfp = 12, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x11c1f8e0, +@@ -252,6 +269,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 240, ++ .ref_hfp = 16, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1e635d7f, +@@ -269,6 +288,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 243, ++ .ref_hfp = 12, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x11c1f8e0, +@@ -284,6 +305,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 243, ++ .ref_hfp = 16, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x1e635d7f, +@@ -308,11 +331,11 @@ void rp1vec_hw_setup(struct rp1_vec *vec + { + unsigned int i, mode_family, mode_ilaced, mode_narrow; + const struct rp1vec_hwmode *hwm; +- unsigned int w, h; ++ int w, h, hpad, vpad; + + /* Pick the appropriate "base" mode, which we may modify */ + mode_ilaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); +- if (mode->vtotal > 263 * (1 + mode_ilaced)) ++ if (mode->vtotal >= 272 * (1 + mode_ilaced)) + mode_family = 1; + else + mode_family = (tvstd == RP1VEC_TVSTD_PAL_M || tvstd == RP1VEC_TVSTD_PAL60) ? 2 : 0; +@@ -326,13 +349,28 @@ void rp1vec_hw_setup(struct rp1_vec *vec + tvstd, rp1vec_tvstd_names[tvstd]); + + w = mode->hdisplay; +- h = mode->vdisplay; +- if (mode_ilaced) +- h >>= 1; ++ h = mode->vdisplay >> mode_ilaced; + if (w > hwm->total_cols) + w = hwm->total_cols; + if (h > hwm->rows_per_field) +- w = hwm->rows_per_field; ++ h = hwm->rows_per_field; ++ ++ /* ++ * Add padding so a framebuffer with the given dimensions and ++ * [hv]sync_start can be displayed in the chosen hardware mode. ++ * ++ * |<----- mode->hsync_start ----->| ++ * |<------ w ------>| | ++ * | | >|--|< ref_hfp ++ * |<- hpad ->| ++ * |<------------ total_cols ----------->| ++ * ________FRAMEBUFFERCONTENTS__________ ++ * ' `--\____/-<\/\/\>-' ++ */ ++ hpad = max(0, mode->hsync_start - hwm->ref_hfp - w); ++ hpad = min(hpad, hwm->total_cols - w); ++ vpad = max(0, ((mode->vsync_start - hwm->ref_vfp) >> mode_ilaced) - h); ++ vpad = min(vpad, hwm->rows_per_field - h); + + /* Configure the hardware */ + VEC_WRITE(VEC_APB_TIMEOUT, 0x38); +@@ -347,18 +385,18 @@ void rp1vec_hw_setup(struct rp1_vec *vec + BITS(VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1, h - 1)); + VEC_WRITE(VEC_YUV_SCALING, hwm->yuv_scaling); + VEC_WRITE(VEC_BACK_PORCH, +- BITS(VEC_BACK_PORCH_HBP_MINUS1, (hwm->total_cols - w - 1) >> 1) | +- BITS(VEC_BACK_PORCH_VBP_MINUS1, (hwm->rows_per_field - h - 1) >> 1)); ++ BITS(VEC_BACK_PORCH_HBP_MINUS1, hwm->total_cols - w - hpad - 1) | ++ BITS(VEC_BACK_PORCH_VBP_MINUS1, hwm->rows_per_field - h - vpad - 1)); + VEC_WRITE(VEC_FRONT_PORCH, +- BITS(VEC_FRONT_PORCH_HFP_MINUS1, (hwm->total_cols - w - 2) >> 1) | +- BITS(VEC_FRONT_PORCH_VFP_MINUS1, (hwm->rows_per_field - h - 2) >> 1)); ++ BITS(VEC_FRONT_PORCH_HFP_MINUS1, hpad - 1) | ++ BITS(VEC_FRONT_PORCH_VFP_MINUS1, vpad - 1)); + VEC_WRITE(VEC_MODE, + BITS(VEC_MODE_HIGH_WATER, 0xE0) | + BITS(VEC_MODE_ALIGN16, !((w | mode->hdisplay) & 15)) | +- BITS(VEC_MODE_VFP_EN, (hwm->rows_per_field > h + 1)) | +- BITS(VEC_MODE_VBP_EN, (hwm->rows_per_field > h)) | +- BITS(VEC_MODE_HFP_EN, (hwm->total_cols > w + 1)) | +- BITS(VEC_MODE_HBP_EN, (hwm->total_cols > w)) | ++ BITS(VEC_MODE_VFP_EN, (vpad > 0)) | ++ BITS(VEC_MODE_VBP_EN, (hwm->rows_per_field > h + vpad)) | ++ BITS(VEC_MODE_HFP_EN, (hpad > 0)) | ++ BITS(VEC_MODE_HBP_EN, (hwm->total_cols > w + hpad)) | + BITS(VEC_MODE_FIELDS_PER_FRAME_MINUS1, hwm->interlaced) | + BITS(VEC_MODE_FIRST_FIELD_ODD, hwm->first_field_odd)); + for (i = 0; i < ARRAY_SIZE(hwm->back_end_regs); ++i) { diff --git a/target/linux/bcm27xx/patches-6.1/950-1245-ARM-pl011-Add-rs485-to-the-RP1-support.patch b/target/linux/bcm27xx/patches-6.1/950-1245-ARM-pl011-Add-rs485-to-the-RP1-support.patch new file mode 100644 index 0000000000..c94619c914 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1245-ARM-pl011-Add-rs485-to-the-RP1-support.patch @@ -0,0 +1,24 @@ +From ab8ba584f91576c41d921076221ceb48e2930ae0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jan 2024 11:08:03 +0000 +Subject: [PATCH] ARM: pl011: Add rs485 to the RP1 support + +pl011_axi_probe, added for RP1 support, lacks the rs485 additions that +appeared during its development. + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/amba-pl011.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -3026,6 +3026,8 @@ static int pl011_axi_probe(struct platfo + uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; + uap->port.irq = irq; + uap->port.ops = &amba_pl011_pops; ++ uap->port.rs485_config = pl011_rs485_config; ++ uap->port.rs485_supported = pl011_rs485_supported; + + snprintf(uap->type, sizeof(uap->type), "PL011 AXI"); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1246-fixup-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch b/target/linux/bcm27xx/patches-6.1/950-1246-fixup-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch new file mode 100644 index 0000000000..8fc8d0c768 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1246-fixup-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch @@ -0,0 +1,38 @@ +From 3bb5880ab3dd31f75c07c3c33bf29c5d469b28f3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jan 2024 15:41:21 +0000 +Subject: [PATCH] fixup! irqchip: irq-bcm2712-mip: Support for 2712's MIP + +Use irq_domain_add_hierarchy so that the root pointer is initialised +correctly. Failure to do so leads to (at least) lockdep warnings when +they are enabled. + +See: https://github.com/raspberrypi/linux/issues/5866 + +Signed-off-by: Phil Elwell +--- + drivers/irqchip/irq-bcm2712-mip.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/irqchip/irq-bcm2712-mip.c ++++ b/drivers/irqchip/irq-bcm2712-mip.c +@@ -209,16 +209,14 @@ static int mip_init_domains(struct mip_p + return -ENXIO; + } + +- middle_domain = irq_domain_add_tree(NULL, +- &mip_irq_domain_ops, +- priv); ++ middle_domain = irq_domain_add_hierarchy(gic_domain, 0, 0, NULL, ++ &mip_irq_domain_ops, ++ priv); + if (!middle_domain) { + pr_err("Failed to create the MIP middle domain\n"); + return -ENOMEM; + } + +- middle_domain->parent = gic_domain; +- + msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), + &mip_msi_domain_info, + middle_domain); diff --git a/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch b/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch index c1b4879a7c..cabe36ba71 100644 --- a/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch +++ b/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch @@ -15,7 +15,7 @@ Signed-off-by: Álvaro Fernández Rojas --- a/drivers/char/hw_random/iproc-rng200.c +++ b/drivers/char/hw_random/iproc-rng200.c -@@ -252,6 +252,7 @@ static int iproc_rng200_probe(struct pla +@@ -253,6 +253,7 @@ static int iproc_rng200_probe(struct pla priv->rng.name = pdev->name; priv->rng.cleanup = iproc_rng200_cleanup; diff --git a/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch b/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch index 7728ec1094..772e905ecb 100644 --- a/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch +++ b/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch @@ -19,7 +19,7 @@ Subject: [PATCH 210/210] b44: register adm switch #include #include -@@ -2243,6 +2245,69 @@ static void b44_adjust_link(struct net_d +@@ -2245,6 +2247,69 @@ static void b44_adjust_link(struct net_d } } @@ -89,7 +89,7 @@ Subject: [PATCH 210/210] b44: register adm switch static int b44_register_phy_one(struct b44 *bp) { __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; -@@ -2279,6 +2344,9 @@ static int b44_register_phy_one(struct b +@@ -2281,6 +2346,9 @@ static int b44_register_phy_one(struct b if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) && (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) { @@ -99,7 +99,7 @@ Subject: [PATCH 210/210] b44: register adm switch dev_info(sdev->dev, "could not find PHY at %i, use fixed one\n", bp->phy_addr); -@@ -2473,6 +2541,7 @@ static void b44_remove_one(struct ssb_de +@@ -2475,6 +2543,7 @@ static void b44_remove_one(struct ssb_de unregister_netdev(dev); if (bp->flags & B44_FLAG_EXTERNAL_PHY) b44_unregister_phy_one(bp); diff --git a/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch b/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch index bedebc415e..ca7123f2a3 100644 --- a/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch +++ b/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch @@ -1,6 +1,6 @@ --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c -@@ -429,10 +429,34 @@ static void b44_wap54g10_workaround(stru +@@ -430,10 +430,34 @@ static void b44_wap54g10_workaround(stru error: pr_warn("PHY: cannot reset MII transceiver isolate bit\n"); } @@ -35,7 +35,7 @@ #endif static int b44_setup_phy(struct b44 *bp) -@@ -441,6 +465,7 @@ static int b44_setup_phy(struct b44 *bp) +@@ -442,6 +466,7 @@ static int b44_setup_phy(struct b44 *bp) int err; b44_wap54g10_workaround(bp); @@ -43,7 +43,7 @@ if (bp->flags & B44_FLAG_EXTERNAL_PHY) return 0; -@@ -2173,6 +2198,8 @@ static int b44_get_invariants(struct b44 +@@ -2175,6 +2200,8 @@ static int b44_get_invariants(struct b44 * valid PHY address. */ bp->phy_addr &= 0x1F; diff --git a/target/linux/bmips/Makefile b/target/linux/bmips/Makefile index f45a70c289..c391e4b785 100644 --- a/target/linux/bmips/Makefile +++ b/target/linux/bmips/Makefile @@ -9,8 +9,7 @@ BOARDNAME:=Broadcom BMIPS SUBTARGETS:=bcm6318 bcm6328 bcm6358 bcm6362 bcm6368 bcm63268 FEATURES:=gpio squashfs usb -KERNEL_PATCHVER:=5.15 -KERNEL_TESTING_PATCHVER:=6.1 +KERNEL_PATCHVER:=6.1 define Target/Description Build firmware images for BCM33xx cable modem chips, diff --git a/target/linux/bmips/bcm6318/config-5.15 b/target/linux/bmips/bcm6318/config-5.15 deleted file mode 100644 index 50401a58e8..0000000000 --- a/target/linux/bmips/bcm6318/config-5.15 +++ /dev/null @@ -1,271 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_BCM6318=y -# CONFIG_PCIE_BCM6328 is not set -CONFIG_PCIE_PME=y -# CONFIG_PCI_BCM6348 is not set -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -CONFIG_PINCTRL_BCM6318=y -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -# CONFIG_SPI_BCM63XX is not set -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm63268/config-5.15 b/target/linux/bmips/bcm63268/config-5.15 deleted file mode 100644 index 09754e9f8b..0000000000 --- a/target/linux/bmips/bcm63268/config-5.15 +++ /dev/null @@ -1,285 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -CONFIG_CLK_BCM63268_TIMER=y -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_BCM2835=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_BCM6318 is not set -CONFIG_PCIE_BCM6328=y -CONFIG_PCIE_PME=y -# CONFIG_PCI_BCM6348 is not set -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -CONFIG_PINCTRL_BCM63268=y -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network b/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network index 391e38c4dc..104f20ef0e 100644 --- a/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network +++ b/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network @@ -11,6 +11,7 @@ arcadyan,ar7516) ;; comtrend,ar-5381u |\ comtrend,ar-5387un |\ +innacomm,w3400v6 |\ nucom,r5010unv2) ucidef_set_bridge_device switch ucidef_set_interface_lan "lan1 lan2 lan3 lan4" diff --git a/target/linux/bmips/bcm6328/config-5.15 b/target/linux/bmips/bcm6328/config-5.15 deleted file mode 100644 index 1e7712ead6..0000000000 --- a/target/linux/bmips/bcm6328/config-5.15 +++ /dev/null @@ -1,283 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_BCM6318 is not set -CONFIG_PCIE_BCM6328=y -CONFIG_PCIE_PME=y -CONFIG_PCI_BCM6348=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -CONFIG_PINCTRL_BCM6328=y -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -# CONFIG_SPI_BCM63XX is not set -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6358/config-5.15 b/target/linux/bmips/bcm6358/config-5.15 deleted file mode 100644 index 5d7a299444..0000000000 --- a/target/linux/bmips/bcm6358/config-5.15 +++ /dev/null @@ -1,265 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -CONFIG_BCM6348_ENET=y -# CONFIG_BCM6368_ENETSW is not set -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -# CONFIG_MDIO_BUS_MUX_BCM6368 is not set -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_PADATA=y -CONFIG_PCI=y -# CONFIG_PCIE_BCM6318 is not set -# CONFIG_PCIE_BCM6328 is not set -CONFIG_PCI_BCM6348=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -CONFIG_PINCTRL_BCM6358=y -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -# CONFIG_SOC_BCM63XX is not set -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -# CONFIG_SPI_BCM63XX_HSSPI is not set -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6362/config-5.15 b/target/linux/bmips/bcm6362/config-5.15 deleted file mode 100644 index 5f9b528d95..0000000000 --- a/target/linux/bmips/bcm6362/config-5.15 +++ /dev/null @@ -1,285 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_BCM2835=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_BCM6318 is not set -CONFIG_PCIE_BCM6328=y -CONFIG_PCIE_PME=y -# CONFIG_PCI_BCM6348 is not set -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -CONFIG_PINCTRL_BCM6362=y -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6368/config-5.15 b/target/linux/bmips/bcm6368/config-5.15 deleted file mode 100644 index 910d36ce0b..0000000000 --- a/target/linux/bmips/bcm6368/config-5.15 +++ /dev/null @@ -1,281 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_BCM2835=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_PADATA=y -CONFIG_PCI=y -# CONFIG_PCIE_BCM6318 is not set -# CONFIG_PCIE_BCM6328 is not set -CONFIG_PCI_BCM6348=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -CONFIG_PINCTRL_BCM6368=y -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -# CONFIG_SOC_BCM63XX is not set -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -# CONFIG_SPI_BCM63XX_HSSPI is not set -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi b/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi index 4e4431f27c..a389187d8d 100644 --- a/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi +++ b/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi @@ -183,7 +183,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts b/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts index d4520661a5..3f830f058e 100644 --- a/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts +++ b/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts @@ -166,7 +166,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts b/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts index bfa9835b26..3c79d38bfb 100644 --- a/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts +++ b/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts @@ -191,7 +191,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts b/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts index be7f90fbd9..b0576748d3 100644 --- a/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts +++ b/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts @@ -181,7 +181,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts index 3321bbd004..052f61002b 100644 --- a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts +++ b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts @@ -85,7 +85,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { reg = <0x000000 0x010000>; label = "cfe"; read-only; diff --git a/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts b/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts index 779f1da1b9..649c595848 100644 --- a/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts +++ b/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts @@ -69,7 +69,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "cfe"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts b/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts index fc7462810c..09e6f99389 100644 --- a/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts +++ b/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts @@ -73,7 +73,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { reg = <0x000000 0x010000>; label = "cfe"; read-only; diff --git a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts index ba15a64265..7ee87c636e 100644 --- a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts +++ b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts @@ -91,7 +91,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { reg = <0x000000 0x010000>; label = "cfe"; read-only; diff --git a/target/linux/bmips/dts/bcm6328-innacomm-w3400v6.dts b/target/linux/bmips/dts/bcm6328-innacomm-w3400v6.dts new file mode 100644 index 0000000000..f2f70fcb17 --- /dev/null +++ b/target/linux/bmips/dts/bcm6328-innacomm-w3400v6.dts @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "bcm6328.dtsi" + +/ { + model = "Innacomm W3400V6"; + compatible = "innacomm,w3400v6", "brcm,bcm6328"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_green; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + + wps { + label = "wps"; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + }; + + bcm4318-sprom { + compatible = "brcm,bcma-sprom"; + + pci-bus = <1>; + pci-dev = <0>; + + nvmem-cells = <&macaddr_cfe_6a0 1>; + nvmem-cell-names = "mac-address"; + + brcm,sprom = "brcm/bcm4318-sprom.bin"; + }; +}; + +ðernet { + status = "okay"; + + nvmem-cells = <&macaddr_cfe_6a0 0>; + nvmem-cell-names = "mac-address"; +}; + +&hsspi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <16666667>; + spi-tx-bus-width = <2>; + spi-rx-bus-width = <2>; + reg = <0>; + + #address-cells = <1>; + #size-cells = <1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x000000 0x010000>; + label = "cfe"; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_cfe_6a0: macaddr@6a0 { + compatible = "mac-base"; + reg = <0x6a0 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@10000 { + compatible = "brcm,bcm963xx-imagetag"; + reg = <0x010000 0x7e0000>; + label = "firmware"; + }; + + partition@7f0000 { + reg = <0x7f0000 0x010000>; + label = "nvram"; + }; + }; + }; +}; + +&leds { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_leds>; + + led@1 { + reg = <1>; + active-low; + label = "green:internet"; + }; + + led@2 { + reg = <2>; + active-low; + label = "red:internet"; + }; + + led@3 { + reg = <3>; + active-low; + label = "green:dsl"; + }; + + led_power_green: led@4 { + reg = <4>; + active-low; + label = "green:power"; + default-state = "on"; + }; + + led_power_red: led@5 { + reg = <5>; + active-low; + label = "red:power"; + panic-indicator; + }; + + led@11 { + reg = <11>; + active-low; + label = "green:wps"; + }; +}; + +&pcie { + status = "okay"; +}; + +&pinctrl { + pinctrl_leds: leds { + function = "led"; + pins = "gpio1", "gpio2", "gpio3", + "gpio4", "gpio5", "gpio11"; + }; +}; + +&switch0 { + ports { + port@0 { + reg = <0>; + label = "lan4"; + + phy-handle = <&phy1>; + phy-mode = "mii"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + + phy-handle = <&phy2>; + phy-mode = "mii"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + + phy-handle = <&phy3>; + phy-mode = "mii"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + + phy-handle = <&phy4>; + phy-mode = "mii"; + }; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts b/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts index b9cbae7af8..d096a1a42c 100644 --- a/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts +++ b/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts @@ -71,7 +71,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "cfe"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts b/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts index aefa72235f..438f1d5fec 100644 --- a/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts +++ b/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts @@ -187,7 +187,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts index c30612191e..c2693fa716 100644 --- a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts +++ b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts @@ -178,7 +178,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "cfe"; reg = <0x000000 0x020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts b/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts index 47be99133d..32682b2610 100644 --- a/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts +++ b/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts @@ -160,7 +160,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts b/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts index 53a1c0c01f..f7182b78da 100644 --- a/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts +++ b/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts @@ -212,7 +212,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0004000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts b/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts index c5e2e7f67f..fec67d0db9 100644 --- a/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts +++ b/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts @@ -174,7 +174,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts index eecf3806f2..63a07fe70e 100644 --- a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts +++ b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts @@ -101,7 +101,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts index fb86adb899..937fbdd1a1 100644 --- a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts +++ b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts @@ -101,7 +101,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi b/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi index 97836e92e0..c647559d6c 100644 --- a/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi +++ b/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi @@ -203,7 +203,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts b/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts index 8d6135fbdd..0f74c4b902 100644 --- a/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts +++ b/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts @@ -152,7 +152,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts b/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts index 53d20ecba3..70572b49a9 100644 --- a/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts +++ b/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts @@ -165,7 +165,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts b/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts index db7f9b0e5b..00017238c8 100644 --- a/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts +++ b/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts @@ -184,7 +184,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x020000>; read-only; diff --git a/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c b/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c index 321e95dbbb..b72a788378 100644 --- a/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c +++ b/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c @@ -22,10 +22,19 @@ #include #include -/* MTU */ -#define ENETSW_TAG_SIZE (6 + VLAN_HLEN) -#define ENETSW_MTU_OVERHEAD (VLAN_ETH_HLEN + VLAN_HLEN + \ - ENETSW_TAG_SIZE) +/* TODO: Bigger frames may work but we do not trust that they are safe on all + * platforms so more research is needed, a max frame size of 2048 has been + * tested. We use the safe frame size 1542 which is 1532 plus DSA and VLAN + * overhead. + */ +#define ENETSW_MAX_FRAME 1542 +#define ENETSW_DSA_TAG_SIZE 6 +/* The MTU in Linux does not include ethernet or VLAN headers, but it DOES + * include the DSA overhead (the framework will increase the MTU to fit + * any DSA header). + */ +#define ENETSW_MAX_MTU (ENETSW_MAX_FRAME - VLAN_ETH_HLEN - \ + VLAN_HLEN) #define ENETSW_FRAG_SIZE(x) (SKB_DATA_ALIGN(NET_SKB_PAD + x + \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))) @@ -1006,7 +1015,7 @@ static int bcm6368_enetsw_probe(struct platform_device *pdev) dev_info(dev, "random mac\n"); } - priv->rx_buf_size = ALIGN(ndev->mtu + ENETSW_MTU_OVERHEAD, + priv->rx_buf_size = ALIGN(ENETSW_MAX_FRAME, ENETSW_DMA_MAXBURST * 4); priv->rx_frag_size = ENETSW_FRAG_SIZE(priv->rx_buf_size); @@ -1066,8 +1075,8 @@ static int bcm6368_enetsw_probe(struct platform_device *pdev) /* register netdevice */ ndev->netdev_ops = &bcm6368_enetsw_ops; ndev->min_mtu = ETH_ZLEN; - ndev->mtu = ETH_DATA_LEN + ENETSW_TAG_SIZE; - ndev->max_mtu = ETH_DATA_LEN + ENETSW_TAG_SIZE; + ndev->mtu = ETH_DATA_LEN; + ndev->max_mtu = ENETSW_MAX_MTU; #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) netif_napi_add(ndev, &priv->napi, bcm6368_enetsw_poll); #else diff --git a/target/linux/bmips/image/bcm6328.mk b/target/linux/bmips/image/bcm6328.mk index fd0cf16dbb..b28926b1e7 100644 --- a/target/linux/bmips/image/bcm6328.mk +++ b/target/linux/bmips/image/bcm6328.mk @@ -39,6 +39,18 @@ define Device/comtrend_ar-5387un endef TARGET_DEVICES += comtrend_ar-5387un +define Device/innacomm_w3400v6 + $(Device/bcm63xx-cfe) + DEVICE_VENDOR := Innacomm + DEVICE_MODEL := W3400V6 + CHIP_ID := 6328 + CFE_BOARD_ID := 96328ang + FLASH_MB := 8 + DEVICE_PACKAGES += $(B43_PACKAGES) \ + broadcom-4318-sprom kmod-leds-bcm6328 +endef +TARGET_DEVICES += innacomm_w3400v6 + define Device/nucom_r5010unv2 $(Device/bcm63xx-cfe) DEVICE_VENDOR := NuCom diff --git a/target/linux/bmips/patches-5.15/100-irqchip-add-support-for-bcm6345-style-external-inter.patch b/target/linux/bmips/patches-5.15/100-irqchip-add-support-for-bcm6345-style-external-inter.patch deleted file mode 100644 index 44cdb068f9..0000000000 --- a/target/linux/bmips/patches-5.15/100-irqchip-add-support-for-bcm6345-style-external-inter.patch +++ /dev/null @@ -1,373 +0,0 @@ -From cf908990d4a8ccdb73ee4484aa8cadad379ca314 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Sun, 30 Nov 2014 14:54:27 +0100 -Subject: [PATCH] irqchip: add support for bcm6345-style external interrupt - controller - -Signed-off-by: Jonas Gorski ---- - .../brcm,bcm6345-ext-intc.txt | 29 ++ - drivers/irqchip/Kconfig | 4 + - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-bcm6345-ext.c | 280 ++++++++++++++++++ - include/linux/irqchip/irq-bcm6345-ext.h | 14 + - 5 files changed, 328 insertions(+) - create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt - create mode 100644 drivers/irqchip/irq-bcm6345-ext.c - create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt -@@ -0,0 +1,29 @@ -+Broadcom BCM6345-style external interrupt controller -+ -+Required properties: -+ -+- compatible: Should be "brcm,bcm6345-ext-intc" or "brcm,bcm6318-ext-intc". -+- reg: Specifies the base physical addresses and size of the registers. -+- interrupt-controller: identifies the node as an interrupt controller. -+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt -+ source, Should be 2. -+- interrupt-parent: Specifies the phandle to the parent interrupt controller -+ this one is cascaded from. -+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller -+ node, valid values depend on the type of parent interrupt controller. -+ -+Optional properties: -+ -+- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the -+ register. Defaults to 4. -+ -+Example: -+ -+ext_intc: interrupt-controller@10000018 { -+ compatible = "brcm,bcm6345-ext-intc"; -+ interrupt-parent = <&periph_intc>; -+ #interrupt-cells = <2>; -+ reg = <0x10000018 0x4>; -+ interrupt-controller; -+ interrupts = <24>, <25>, <26>, <27>; -+}; ---- a/drivers/irqchip/Kconfig -+++ b/drivers/irqchip/Kconfig -@@ -108,6 +108,10 @@ config I8259 - bool - select IRQ_DOMAIN - -+config BCM6345_EXT_IRQ -+ bool "BCM6345 External IRQ Controller" -+ select IRQ_DOMAIN -+ - config BCM6345_L1_IRQ - bool - select GENERIC_IRQ_CHIP ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -62,6 +62,7 @@ obj-$(CONFIG_XTENSA_MX) += irq-xtensa- - obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o - obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o - obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o -+obj-$(CONFIG_BCM6345_EXT_IRQ) += irq-bcm6345-ext.o - obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o - obj-$(CONFIG_BCM7038_L1_IRQ) += irq-bcm7038-l1.o - obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o ---- /dev/null -+++ b/drivers/irqchip/irq-bcm6345-ext.c -@@ -0,0 +1,280 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2014 Jonas Gorski -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_IRQS 4 -+ -+#define EXTIRQ_CFG_SENSE 0 -+#define EXTIRQ_CFG_STAT 1 -+#define EXTIRQ_CFG_CLEAR 2 -+#define EXTIRQ_CFG_MASK 3 -+#define EXTIRQ_CFG_BOTHEDGE 4 -+#define EXTIRQ_CFG_LEVELSENSE 5 -+ -+struct intc_data { -+ struct irq_chip chip; -+ struct irq_domain *domain; -+ raw_spinlock_t lock; -+ -+ int parent_irq[MAX_IRQS]; -+ void __iomem *reg; -+ int shift; -+ unsigned int toggle_clear_on_ack:1; -+}; -+ -+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc) -+{ -+ struct intc_data *data = irq_desc_get_handler_data(desc); -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ unsigned int irq = irq_desc_get_irq(desc); -+ unsigned int idx; -+ -+ chained_irq_enter(chip, desc); -+ -+ for (idx = 0; idx < MAX_IRQS; idx++) { -+ if (data->parent_irq[idx] != irq) -+ continue; -+ -+ generic_handle_irq(irq_find_mapping(data->domain, idx)); -+ } -+ -+ chained_irq_exit(chip, desc); -+} -+ -+static void bcm6345_ext_intc_irq_ack(struct irq_data *data) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ u32 reg; -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ __raw_writel(reg | (1 << (hwirq + EXTIRQ_CFG_CLEAR * priv->shift)), -+ priv->reg); -+ if (priv->toggle_clear_on_ack) -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+} -+ -+static void bcm6345_ext_intc_irq_mask(struct irq_data *data) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ u32 reg; -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift)); -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+} -+ -+static void bcm6345_ext_intc_irq_unmask(struct irq_data *data) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ u32 reg; -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ reg |= 1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift); -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+} -+ -+static int bcm6345_ext_intc_set_type(struct irq_data *data, -+ unsigned int flow_type) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ bool levelsense = 0, sense = 0, bothedge = 0; -+ u32 reg; -+ -+ flow_type &= IRQ_TYPE_SENSE_MASK; -+ -+ if (flow_type == IRQ_TYPE_NONE) -+ flow_type = IRQ_TYPE_LEVEL_LOW; -+ -+ switch (flow_type) { -+ case IRQ_TYPE_EDGE_BOTH: -+ bothedge = 1; -+ break; -+ -+ case IRQ_TYPE_EDGE_RISING: -+ sense = 1; -+ break; -+ -+ case IRQ_TYPE_EDGE_FALLING: -+ break; -+ -+ case IRQ_TYPE_LEVEL_HIGH: -+ levelsense = 1; -+ sense = 1; -+ break; -+ -+ case IRQ_TYPE_LEVEL_LOW: -+ levelsense = 1; -+ break; -+ -+ default: -+ pr_err("bogus flow type combination given!\n"); -+ return -EINVAL; -+ } -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ -+ if (levelsense) -+ reg |= 1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift); -+ else -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift)); -+ if (sense) -+ reg |= 1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift); -+ else -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift)); -+ if (bothedge) -+ reg |= 1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift); -+ else -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift)); -+ -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+ -+ irqd_set_trigger_type(data, flow_type); -+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) -+ irq_set_handler_locked(data, handle_level_irq); -+ else -+ irq_set_handler_locked(data, handle_edge_irq); -+ -+ return 0; -+} -+ -+static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq, -+ irq_hw_number_t hw) -+{ -+ struct intc_data *priv = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops bcm6345_ext_domain_ops = { -+ .xlate = irq_domain_xlate_twocell, -+ .map = bcm6345_ext_intc_map, -+}; -+ -+static int __init __bcm6345_ext_intc_init(struct device_node *node, -+ int num_irqs, int *irqs, -+ void __iomem *reg, int shift, -+ bool toggle_clear_on_ack) -+{ -+ struct intc_data *data; -+ unsigned int i; -+ -+ data = kzalloc(sizeof(*data), GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ -+ raw_spin_lock_init(&data->lock); -+ -+ for (i = 0; i < num_irqs; i++) { -+ data->parent_irq[i] = irqs[i]; -+ -+ irq_set_handler_data(irqs[i], data); -+ irq_set_chained_handler(irqs[i], bcm6345_ext_intc_irq_handle); -+ } -+ -+ data->reg = reg; -+ data->shift = shift; -+ data->toggle_clear_on_ack = toggle_clear_on_ack; -+ -+ data->chip.name = "bcm6345-ext-intc"; -+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack; -+ data->chip.irq_mask = bcm6345_ext_intc_irq_mask; -+ data->chip.irq_unmask = bcm6345_ext_intc_irq_unmask; -+ data->chip.irq_set_type = bcm6345_ext_intc_set_type; -+ -+ data->domain = irq_domain_add_linear(node, num_irqs, -+ &bcm6345_ext_domain_ops, data); -+ if (!data->domain) { -+ kfree(data); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg, -+ int shift) -+{ -+ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift, false); -+} -+ -+#ifdef CONFIG_OF -+static int __init bcm6345_ext_intc_of_init(struct device_node *node, -+ struct device_node *parent) -+{ -+ int num_irqs, ret = -EINVAL; -+ unsigned i; -+ void __iomem *base; -+ int irqs[MAX_IRQS] = { 0 }; -+ u32 shift; -+ bool toggle_clear_on_ack = false; -+ -+ num_irqs = of_irq_count(node); -+ -+ if (!num_irqs || num_irqs > MAX_IRQS) -+ return -EINVAL; -+ -+ if (of_property_read_u32(node, "brcm,field-width", &shift)) -+ shift = 4; -+ -+ /* on BCM6318 setting CLEAR seems to continuously mask interrupts */ -+ if (of_device_is_compatible(node, "brcm,bcm6318-ext-intc")) -+ toggle_clear_on_ack = true; -+ -+ for (i = 0; i < num_irqs; i++) { -+ irqs[i] = irq_of_parse_and_map(node, i); -+ if (!irqs[i]) -+ return -ENOMEM; -+ } -+ -+ base = of_iomap(node, 0); -+ if (!base) -+ return -ENXIO; -+ -+ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift, -+ toggle_clear_on_ack); -+ if (!ret) -+ return 0; -+ -+ iounmap(base); -+ -+ for (i = 0; i < num_irqs; i++) -+ irq_dispose_mapping(irqs[i]); -+ -+ return ret; -+} -+ -+IRQCHIP_DECLARE(bcm6318_ext_intc, "brcm,bcm6318-ext-intc", -+ bcm6345_ext_intc_of_init); -+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc", -+ bcm6345_ext_intc_of_init); -+#endif ---- /dev/null -+++ b/include/linux/irqchip/irq-bcm6345-ext.h -@@ -0,0 +1,14 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2014 Jonas Gorski -+ */ -+ -+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H -+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H -+ -+void bcm6345_ext_intc_init(int n_irqs, int *irqs, void __iomem *reg, int shift); -+ -+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H */ diff --git a/target/linux/bmips/patches-5.15/200-mips-bmips-automatically-detect-CPU-frequency.patch b/target/linux/bmips/patches-5.15/200-mips-bmips-automatically-detect-CPU-frequency.patch deleted file mode 100644 index e2b73e6ac4..0000000000 --- a/target/linux/bmips/patches-5.15/200-mips-bmips-automatically-detect-CPU-frequency.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 0377ad93031d3e51c2afe44231241185f684b6af Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Fri, 5 Mar 2021 15:14:32 +0100 -Subject: [PATCH] mips: bmips: automatically detect CPU frequency -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some BCM63xx SoCs support multiple CPU frequencies depending on HW config. - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/bmips/setup.c | 197 ++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 190 insertions(+), 7 deletions(-) - ---- a/arch/mips/bmips/setup.c -+++ b/arch/mips/bmips/setup.c -@@ -31,13 +31,52 @@ - - #define RELO_NORMAL_VEC BIT(18) - -+#define REG_BCM6318_SOB ((void __iomem *)CKSEG1ADDR(0x10000900)) -+#define BCM6318_FREQ_SHIFT 23 -+#define BCM6318_FREQ_MASK (0x3 << BCM6318_FREQ_SHIFT) -+ - #define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c)) - #define BCM6328_TP1_DISABLED BIT(9) -+#define REG_BCM6328_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001a40)) -+#define BCM6328_FCVO_SHIFT 7 -+#define BCM6328_FCVO_MASK (0x1f << BCM6328_FCVO_SHIFT) -+ -+#define REG_BCM6358_DDR_PLLC ((void __iomem *)0xfffe12b8) -+#define BCM6358_PLLC_M1_SHIFT 0 -+#define BCM6358_PLLC_M1_MASK (0xff << BCM6358_PLLC_M1_SHIFT) -+#define BCM6358_PLLC_N1_SHIFT 23 -+#define BCM6358_PLLC_N1_MASK (0x3f << BCM6358_PLLC_N1_SHIFT) -+#define BCM6358_PLLC_N2_SHIFT 29 -+#define BCM6358_PLLC_N2_MASK (0x7 << BCM6358_PLLC_N2_SHIFT) -+ -+#define REG_BCM6362_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) -+#define BCM6362_FCVO_SHIFT 1 -+#define BCM6362_FCVO_MASK (0x1f << BCM6362_FCVO_SHIFT) -+ -+#define REG_BCM6368_DDR_PLLC ((void __iomem *)CKSEG1ADDR(0x100012a0)) -+#define BCM6368_PLLC_P1_SHIFT 0 -+#define BCM6368_PLLC_P1_MASK (0xf << BCM6368_PLLC_P1_SHIFT) -+#define BCM6368_PLLC_P2_SHIFT 4 -+#define BCM6368_PLLC_P2_MASK (0xf << BCM6368_PLLC_P2_SHIFT) -+#define BCM6368_PLLC_NDIV_SHIFT 16 -+#define BCM6368_PLLC_NDIV_MASK (0x1ff << BCM6368_PLLC_NDIV_SHIFT) -+#define REG_BCM6368_DDR_PLLD ((void __iomem *)CKSEG1ADDR(0x100012a4)) -+#define BCM6368_PLLD_MDIV_SHIFT 0 -+#define BCM6368_PLLD_MDIV_MASK (0xff << BCM6368_PLLD_MDIV_SHIFT) -+ -+#define REG_BCM63268_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) -+#define BCM63268_FCVO_SHIFT 21 -+#define BCM63268_FCVO_MASK (0xf << BCM63268_FCVO_SHIFT) - - extern bool bmips_rac_flush_disable; - - static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000; - -+struct bmips_cpufreq { -+ const char *compatible; -+ u32 (*cpu_freq)(void); -+}; -+ - struct bmips_quirk { - const char *compatible; - void (*quirk_fn)(void); -@@ -142,17 +181,161 @@ const char *get_system_type(void) - return "Generic BMIPS kernel"; - } - -+static u32 bcm6318_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM6318_SOB); -+ -+ switch ((val & BCM6318_FREQ_MASK) >> BCM6318_FREQ_SHIFT) { -+ case 0: -+ return 166000000; -+ case 2: -+ return 250000000; -+ case 3: -+ return 333000000; -+ case 1: -+ return 400000000; -+ default: -+ return 0; -+ } -+} -+ -+static u32 bcm6328_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM6328_MISC_SB); -+ -+ switch ((val & BCM6328_FCVO_MASK) >> BCM6328_FCVO_SHIFT) { -+ case 0x12: -+ case 0x14: -+ case 0x19: -+ return 160000000; -+ case 0x1c: -+ return 192000000; -+ case 0x13: -+ case 0x15: -+ return 200000000; -+ case 0x1a: -+ return 384000000; -+ case 0x16: -+ return 400000000; -+ default: -+ return 320000000; -+ } -+} -+ -+static u32 bcm6358_cpufreq(void) -+{ -+ u32 val, n1, n2, m1; -+ -+ val = __raw_readl(REG_BCM6358_DDR_PLLC); -+ n1 = (val & BCM6358_PLLC_N1_MASK) >> BCM6358_PLLC_N1_SHIFT; -+ n2 = (val & BCM6358_PLLC_N2_MASK) >> BCM6358_PLLC_N2_SHIFT; -+ m1 = (val & BCM6358_PLLC_M1_MASK) >> BCM6358_PLLC_M1_SHIFT; -+ -+ return (16 * 1000000 * n1 * n2) / m1; -+} -+ -+static u32 bcm6362_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM6362_MISC_SB); -+ -+ switch ((val & BCM6362_FCVO_MASK) >> BCM6362_FCVO_SHIFT) { -+ case 0x04: -+ case 0x0c: -+ case 0x14: -+ case 0x1c: -+ return 160000000; -+ case 0x15: -+ case 0x1d: -+ return 200000000; -+ case 0x03: -+ case 0x0b: -+ case 0x13: -+ case 0x1b: -+ return 240000000; -+ case 0x07: -+ case 0x17: -+ return 384000000; -+ case 0x05: -+ case 0x0e: -+ case 0x16: -+ case 0x1e: -+ case 0x1f: -+ return 400000000; -+ case 0x06: -+ return 440000000; -+ default: -+ return 320000000; -+ } -+} -+ -+static u32 bcm6368_cpufreq(void) -+{ -+ u32 val, p1, p2, ndiv, m1; -+ -+ val = __raw_readl(REG_BCM6368_DDR_PLLC); -+ p1 = (val & BCM6368_PLLC_P1_MASK) >> BCM6368_PLLC_P1_SHIFT; -+ p2 = (val & BCM6368_PLLC_P2_MASK) >> BCM6368_PLLC_P2_SHIFT; -+ ndiv = (val & BCM6368_PLLC_NDIV_MASK) >> -+ BCM6368_PLLC_NDIV_SHIFT; -+ -+ val = __raw_readl(REG_BCM6368_DDR_PLLD); -+ m1 = (val & BCM6368_PLLD_MDIV_MASK) >> BCM6368_PLLD_MDIV_SHIFT; -+ -+ return (((64 * 1000000) / p1) * p2 * ndiv) / m1; -+} -+ -+static u32 bcm63268_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM63268_MISC_SB); -+ -+ switch ((val & BCM63268_FCVO_MASK) >> BCM63268_FCVO_SHIFT) { -+ case 0x3: -+ case 0xe: -+ return 320000000; -+ case 0xa: -+ return 333000000; -+ case 0x2: -+ case 0xb: -+ case 0xf: -+ return 400000000; -+ default: -+ return 0; -+ } -+} -+ -+static const struct bmips_cpufreq bmips_cpufreq_list[] = { -+ { "brcm,bcm6318", &bcm6318_cpufreq }, -+ { "brcm,bcm6328", &bcm6328_cpufreq }, -+ { "brcm,bcm6358", &bcm6358_cpufreq }, -+ { "brcm,bcm6362", &bcm6362_cpufreq }, -+ { "brcm,bcm6368", &bcm6368_cpufreq }, -+ { "brcm,bcm63268", &bcm63268_cpufreq }, -+ { /* sentinel */ } -+}; -+ - void __init plat_time_init(void) - { -+ const struct bmips_cpufreq *cf; - struct device_node *np; -- u32 freq; -+ u32 freq = 0; - -- np = of_find_node_by_name(NULL, "cpus"); -- if (!np) -- panic("missing 'cpus' DT node"); -- if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0) -- panic("missing 'mips-hpt-frequency' property"); -- of_node_put(np); -+ for (cf = bmips_cpufreq_list; cf->cpu_freq; cf++) { -+ if (of_flat_dt_is_compatible(of_get_flat_dt_root(), -+ cf->compatible)) { -+ freq = cf->cpu_freq() / 2; -+ printk("%s detected @ %u MHz\n", cf->compatible, freq / 500000); -+ break; -+ } -+ } -+ -+ if (!freq) { -+ np = of_find_node_by_name(NULL, "cpus"); -+ if (!np) -+ panic("missing 'cpus' DT node"); -+ if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0) -+ panic("missing 'mips-hpt-frequency' property"); -+ of_node_put(np); -+ } - - mips_hpt_frequency = freq; - } diff --git a/target/linux/bmips/patches-5.15/201-mips-bmips-automatically-detect-RAM-size.patch b/target/linux/bmips/patches-5.15/201-mips-bmips-automatically-detect-RAM-size.patch deleted file mode 100644 index c0bdb0d5ce..0000000000 --- a/target/linux/bmips/patches-5.15/201-mips-bmips-automatically-detect-RAM-size.patch +++ /dev/null @@ -1,196 +0,0 @@ -From f9ee3f28ecb979c77423be965ef9dd313bdb9e9b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Mon, 8 Mar 2021 16:58:34 +0100 -Subject: [PATCH] mips: bmips: automatically detect RAM size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some devices have different amounts of RAM installed depending on HW revision. - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/bmips/setup.c | 119 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 119 insertions(+) - ---- a/arch/mips/bmips/setup.c -+++ b/arch/mips/bmips/setup.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -34,13 +35,16 @@ - #define REG_BCM6318_SOB ((void __iomem *)CKSEG1ADDR(0x10000900)) - #define BCM6318_FREQ_SHIFT 23 - #define BCM6318_FREQ_MASK (0x3 << BCM6318_FREQ_SHIFT) -+#define BCM6318_SDRAM_ADDR ((void __iomem *)CKSEG1ADDR(0x10004000)) - - #define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c)) - #define BCM6328_TP1_DISABLED BIT(9) - #define REG_BCM6328_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001a40)) - #define BCM6328_FCVO_SHIFT 7 - #define BCM6328_FCVO_MASK (0x1f << BCM6328_FCVO_SHIFT) -+#define BCM6328_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000)) - -+#define BCM6358_MEMC_ADDR ((void __iomem *)0xfffe1200) - #define REG_BCM6358_DDR_PLLC ((void __iomem *)0xfffe12b8) - #define BCM6358_PLLC_M1_SHIFT 0 - #define BCM6358_PLLC_M1_MASK (0xff << BCM6358_PLLC_M1_SHIFT) -@@ -52,7 +56,9 @@ - #define REG_BCM6362_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) - #define BCM6362_FCVO_SHIFT 1 - #define BCM6362_FCVO_MASK (0x1f << BCM6362_FCVO_SHIFT) -+#define BCM6362_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000)) - -+#define BCM6368_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10001200)) - #define REG_BCM6368_DDR_PLLC ((void __iomem *)CKSEG1ADDR(0x100012a0)) - #define BCM6368_PLLC_P1_SHIFT 0 - #define BCM6368_PLLC_P1_MASK (0xf << BCM6368_PLLC_P1_SHIFT) -@@ -67,6 +73,21 @@ - #define REG_BCM63268_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) - #define BCM63268_FCVO_SHIFT 21 - #define BCM63268_FCVO_MASK (0xf << BCM63268_FCVO_SHIFT) -+#define BCM63268_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000)) -+ -+#define SDRAM_CFG_REG 0x0 -+#define SDRAM_SPACE_SHIFT 4 -+#define SDRAM_SPACE_MASK (0xf << SDRAM_SPACE_SHIFT) -+ -+#define MEMC_CFG_REG 0x4 -+#define MEMC_CFG_32B_SHIFT 1 -+#define MEMC_CFG_32B_MASK (1 << MEMC_CFG_32B_SHIFT) -+#define MEMC_CFG_COL_SHIFT 3 -+#define MEMC_CFG_COL_MASK (0x3 << MEMC_CFG_COL_SHIFT) -+#define MEMC_CFG_ROW_SHIFT 6 -+#define MEMC_CFG_ROW_MASK (0x3 << MEMC_CFG_ROW_SHIFT) -+ -+#define DDR_CSEND_REG 0x8 - - extern bool bmips_rac_flush_disable; - -@@ -77,6 +98,11 @@ struct bmips_cpufreq { - u32 (*cpu_freq)(void); - }; - -+struct bmips_memsize { -+ const char *compatible; -+ phys_addr_t (*mem_size)(void); -+}; -+ - struct bmips_quirk { - const char *compatible; - void (*quirk_fn)(void); -@@ -340,9 +366,90 @@ void __init plat_time_init(void) - mips_hpt_frequency = freq; - } - -+static inline phys_addr_t bmips_dram_size(unsigned int cols, -+ unsigned int rows, -+ unsigned int is_32b, -+ unsigned int banks) -+{ -+ rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */ -+ cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */ -+ is_32b += 1; -+ -+ return 1 << (cols + rows + is_32b + banks); -+} -+ -+static phys_addr_t _bcm6318_memsize(void __iomem *addr) -+{ -+ u32 val; -+ -+ val = __raw_readl(addr + SDRAM_CFG_REG); -+ val = (val & SDRAM_SPACE_MASK) >> SDRAM_SPACE_SHIFT; -+ -+ return (1 << (val + 20)); -+} -+ -+static phys_addr_t _bcm6328_memsize(void __iomem *addr) -+{ -+ return __raw_readl(addr + DDR_CSEND_REG) << 24; -+} -+ -+static phys_addr_t _bcm6358_memsize(void __iomem *addr) -+{ -+ unsigned int cols, rows, is_32b; -+ u32 val; -+ -+ val = __raw_readl(addr + MEMC_CFG_REG); -+ rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; -+ cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; -+ is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1; -+ -+ return bmips_dram_size(cols, rows, is_32b, 2); -+} -+ -+static phys_addr_t bcm6318_memsize(void) -+{ -+ return _bcm6318_memsize(BCM6318_SDRAM_ADDR); -+} -+ -+static phys_addr_t bcm6328_memsize(void) -+{ -+ return _bcm6328_memsize(BCM6328_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm6358_memsize(void) -+{ -+ return _bcm6358_memsize(BCM6358_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm6362_memsize(void) -+{ -+ return _bcm6328_memsize(BCM6362_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm6368_memsize(void) -+{ -+ return _bcm6358_memsize(BCM6368_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm63268_memsize(void) -+{ -+ return _bcm6328_memsize(BCM63268_MEMC_ADDR); -+} -+ -+static const struct bmips_memsize bmips_memsize_list[] = { -+ { "brcm,bcm6318", &bcm6318_memsize }, -+ { "brcm,bcm6328", &bcm6328_memsize }, -+ { "brcm,bcm6358", &bcm6358_memsize }, -+ { "brcm,bcm6362", &bcm6362_memsize }, -+ { "brcm,bcm6368", &bcm6368_memsize }, -+ { "brcm,bcm63268", &bcm63268_memsize }, -+ { /* sentinel */ } -+}; -+ - void __init plat_mem_setup(void) - { - void *dtb; -+ const struct bmips_memsize *ms; - const struct bmips_quirk *q; - - set_io_port_base(0); -@@ -360,6 +467,18 @@ void __init plat_mem_setup(void) - - __dt_setup_arch(dtb); - -+ for (ms = bmips_memsize_list; ms->mem_size; ms++) { -+ if (of_flat_dt_is_compatible(of_get_flat_dt_root(), -+ ms->compatible)) { -+ phys_addr_t mem = ms->mem_size(); -+ if (mem) { -+ memblock_add(0, mem); -+ printk("%uMB of RAM installed\n", mem >> 20); -+ break; -+ } -+ } -+ } -+ - for (q = bmips_quirk_list; q->quirk_fn; q++) { - if (of_flat_dt_is_compatible(of_get_flat_dt_root(), - q->compatible)) { diff --git a/target/linux/bmips/patches-5.15/202-mips-bmips-tweak-Kconfig-options.patch b/target/linux/bmips/patches-5.15/202-mips-bmips-tweak-Kconfig-options.patch deleted file mode 100644 index 79d4f98e0a..0000000000 --- a/target/linux/bmips/patches-5.15/202-mips-bmips-tweak-Kconfig-options.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 20a4b57c0fafd23ae0f6bcab5b5adf4af4c80280 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Thu, 16 Mar 2023 19:31:21 +0100 -Subject: [PATCH] mips: bmips: tweak Kconfig options -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/Kconfig | 7 +------ - 1 file changed, 1 insertion(+), 6 deletions(-) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -276,25 +276,20 @@ config BMIPS_GENERIC - select SYNC_R4K - select COMMON_CLK - select BCM6345_L1_IRQ -- select BCM7038_L1_IRQ -- select BCM7120_L2_IRQ -- select BRCMSTB_L2_IRQ - select IRQ_MIPS_CPU - select DMA_NONCOHERENT - select SYS_SUPPORTS_32BIT_KERNEL -- select SYS_SUPPORTS_LITTLE_ENDIAN - select SYS_SUPPORTS_BIG_ENDIAN -- select SYS_SUPPORTS_HIGHMEM - select SYS_HAS_CPU_BMIPS32_3300 - select SYS_HAS_CPU_BMIPS4350 - select SYS_HAS_CPU_BMIPS4380 -- select SYS_HAS_CPU_BMIPS5000 - select SWAP_IO_SPACE - select USB_EHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN - select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN - select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN - select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN - select HARDIRQS_SW_RESEND -+ select MIPS_L1_CACHE_SHIFT_4 - help - Build a generic DT-based kernel image that boots on select - BCM33xx cable modem chips, BCM63xx DSL chips, and BCM7xxx set-top diff --git a/target/linux/bmips/patches-5.15/203-mips-bmips-dma-fix-CBR-address.patch b/target/linux/bmips/patches-5.15/203-mips-bmips-dma-fix-CBR-address.patch deleted file mode 100644 index 57bf395e2e..0000000000 --- a/target/linux/bmips/patches-5.15/203-mips-bmips-dma-fix-CBR-address.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 3e4c3863e0cfb8c2abdff6bb494ca69d3d2aed9c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 10 Jun 2023 17:01:40 +0200 -Subject: [PATCH] mips: bmips: dma: fix CBR address -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some BCM63xx SoCs may return CBR address as 0. - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/bmips/dma.c | 12 ++++-------- - arch/mips/bmips/setup.c | 11 ++++------- - 2 files changed, 8 insertions(+), 15 deletions(-) - ---- a/arch/mips/bmips/dma.c -+++ b/arch/mips/bmips/dma.c -@@ -64,11 +64,10 @@ phys_addr_t dma_to_phys(struct device *d - return dma_addr; - } - --bool bmips_rac_flush_disable; -+void __iomem *bmips_cbr_addr; - - void arch_sync_dma_for_cpu_all(void) - { -- void __iomem *cbr = BMIPS_GET_CBR(); - u32 cfg; - - if (boot_cpu_type() != CPU_BMIPS3300 && -@@ -76,13 +75,10 @@ void arch_sync_dma_for_cpu_all(void) - boot_cpu_type() != CPU_BMIPS4380) - return; - -- if (unlikely(bmips_rac_flush_disable)) -- return; -- - /* Flush stale data out of the readahead cache */ -- cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); -- __raw_writel(cfg | 0x100, cbr + BMIPS_RAC_CONFIG); -- __raw_readl(cbr + BMIPS_RAC_CONFIG); -+ cfg = __raw_readl(bmips_cbr_addr + BMIPS_RAC_CONFIG); -+ __raw_writel(cfg | 0x100, bmips_cbr_addr + BMIPS_RAC_CONFIG); -+ __raw_readl(bmips_cbr_addr + BMIPS_RAC_CONFIG); - } - - static int __init bmips_init_dma_ranges(void) ---- a/arch/mips/bmips/setup.c -+++ b/arch/mips/bmips/setup.c -@@ -89,7 +89,7 @@ - - #define DDR_CSEND_REG 0x8 - --extern bool bmips_rac_flush_disable; -+extern void __iomem *bmips_cbr_addr; - - static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000; - -@@ -170,12 +170,6 @@ static void bcm6358_quirks(void) - * disable SMP for now - */ - bmips_smp_enabled = 0; -- -- /* -- * RAC flush causes kernel panics on BCM6358 when booting from TP1 -- * because the bootloader is not initializing it properly. -- */ -- bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31)); - } - - static void bcm6368_quirks(void) -@@ -198,6 +192,11 @@ static const struct bmips_quirk bmips_qu - - void __init prom_init(void) - { -+ if (!(read_c0_brcm_cbr() >> 18)) -+ bmips_cbr_addr = (void __iomem *)0xff400000; -+ else -+ bmips_cbr_addr = BMIPS_GET_CBR(); -+ - bmips_cpu_setup(); - register_bmips_smp_ops(); - } diff --git a/target/linux/bmips/patches-5.15/204-mips-bmips-enable-RAC-on-BMIPS4350.patch b/target/linux/bmips/patches-5.15/204-mips-bmips-enable-RAC-on-BMIPS4350.patch deleted file mode 100644 index 26bd03e329..0000000000 --- a/target/linux/bmips/patches-5.15/204-mips-bmips-enable-RAC-on-BMIPS4350.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 7f862eaedac56b67972393f0a9affcd2fe53479b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20Gonz=C3=A1lez=20Cabanelas?= -Date: Sun, 18 Jun 2023 19:59:25 +0200 -Subject: [PATCH] mips: bmips: enable RAC on BMIPS4350 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The data RAC is left disabled by the bootloader in some SoCs, at least in -the core it boots from. -Enabling this feature increases the performance up to +30% depending on the -task. - -Signed-off-by: Daniel González Cabanelas -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/kernel/smp-bmips.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/mips/kernel/smp-bmips.c -+++ b/arch/mips/kernel/smp-bmips.c -@@ -614,6 +614,20 @@ void bmips_cpu_setup(void) - __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE); - break; - -+ case CPU_BMIPS4350: -+ /* Enable data RAC */ -+ if (!(read_c0_brcm_cmt_local() & (1 << 31))) { -+ cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); -+ __raw_writel(cfg | 0xa, cbr + BMIPS_RAC_CONFIG); -+ __raw_readl(cbr + BMIPS_RAC_CONFIG); -+ } else { -+ cbr = (void __iomem *)0xff400000; -+ cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG_1); -+ __raw_writel(cfg | 0xa, cbr + BMIPS_RAC_CONFIG_1); -+ __raw_readl(cbr + BMIPS_RAC_CONFIG_1); -+ } -+ break; -+ - case CPU_BMIPS4380: - /* CBG workaround for early BMIPS4380 CPUs */ - switch (read_c0_prid()) { diff --git a/target/linux/bmips/patches-5.15/210-macronix_nand_block_protection_support.patch b/target/linux/bmips/patches-5.15/210-macronix_nand_block_protection_support.patch deleted file mode 100644 index 25a16084ef..0000000000 --- a/target/linux/bmips/patches-5.15/210-macronix_nand_block_protection_support.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 5a37811de679bff03e9c5a746f75574910ede964 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 22 Mar 2023 20:52:13 +0100 -Subject: [PATCH] Revert "mtd: rawnand: Macronix: Add support for block - protection" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This reverts commit 03a539c7a118427a6609a26461358c56ac8f3a06. - -Macronix block protection doesn't seem to be supported on Sercomm H-500s -devices since it hangs the device. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/mtd/nand/raw/nand_macronix.c | 72 ---------------------------- - 1 file changed, 72 deletions(-) - ---- a/drivers/mtd/nand/raw/nand_macronix.c -+++ b/drivers/mtd/nand/raw/nand_macronix.c -@@ -12,10 +12,6 @@ - #define MACRONIX_READ_RETRY_BIT BIT(0) - #define MACRONIX_NUM_READ_RETRY_MODES 6 - --#define ONFI_FEATURE_ADDR_MXIC_PROTECTION 0xA0 --#define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38 --#define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0 -- - #define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0 - #define MACRONIX_RANDOMIZER_BIT BIT(1) - #define MACRONIX_RANDOMIZER_ENPGM BIT(0) -@@ -179,73 +175,6 @@ static void macronix_nand_fix_broken_get - ONFI_FEATURE_ADDR_TIMING_MODE, 1); - } - --/* -- * Macronix NAND supports Block Protection by Protectoin(PT) pin; -- * active high at power-on which protects the entire chip even the #WP is -- * disabled. Lock/unlock protection area can be partition according to -- * protection bits, i.e. upper 1/2 locked, upper 1/4 locked and so on. -- */ --static int mxic_nand_lock(struct nand_chip *chip, loff_t ofs, uint64_t len) --{ -- u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; -- int ret; -- -- feature[0] = MXIC_BLOCK_PROTECTION_ALL_LOCK; -- nand_select_target(chip, 0); -- ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, -- feature); -- nand_deselect_target(chip); -- if (ret) -- pr_err("%s all blocks failed\n", __func__); -- -- return ret; --} -- --static int mxic_nand_unlock(struct nand_chip *chip, loff_t ofs, uint64_t len) --{ -- u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; -- int ret; -- -- feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK; -- nand_select_target(chip, 0); -- ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, -- feature); -- nand_deselect_target(chip); -- if (ret) -- pr_err("%s all blocks failed\n", __func__); -- -- return ret; --} -- --static void macronix_nand_block_protection_support(struct nand_chip *chip) --{ -- u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; -- int ret; -- -- bitmap_set(chip->parameters.get_feature_list, -- ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); -- -- feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK; -- nand_select_target(chip, 0); -- ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, -- feature); -- nand_deselect_target(chip); -- if (ret || feature[0] != MXIC_BLOCK_PROTECTION_ALL_LOCK) { -- if (ret) -- pr_err("Block protection check failed\n"); -- -- bitmap_clear(chip->parameters.get_feature_list, -- ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); -- return; -- } -- -- bitmap_set(chip->parameters.set_feature_list, -- ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); -- -- chip->ops.lock_area = mxic_nand_lock; -- chip->ops.unlock_area = mxic_nand_unlock; --} -- - static int nand_power_down_op(struct nand_chip *chip) - { - int ret; -@@ -323,7 +252,6 @@ static int macronix_nand_init(struct nan - - macronix_nand_fix_broken_get_timings(chip); - macronix_nand_onfi_init(chip); -- macronix_nand_block_protection_support(chip); - macronix_nand_deep_power_down_support(chip); - - return 0; diff --git a/target/linux/bmips/patches-5.15/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch b/target/linux/bmips/patches-5.15/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch deleted file mode 100644 index 71ed53235f..0000000000 --- a/target/linux/bmips/patches-5.15/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 590b60fb08cb1e70fe02d3f407c6b3dbe9ad06ff Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Mon, 1 Mar 2021 07:34:39 +0100 -Subject: [PATCH] net: broadcom: add BCM6368 enetsw controller driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This controller is present on BCM6318, BCM6328, BCM6362, BCM6368 and BCM63268 -SoCs. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/net/ethernet/broadcom/Kconfig | 8 ++++++++ - drivers/net/ethernet/broadcom/Makefile | 1 + - 2 files changed, 9 insertions(+) - ---- a/drivers/net/ethernet/broadcom/Kconfig -+++ b/drivers/net/ethernet/broadcom/Kconfig -@@ -68,6 +68,14 @@ config BCM63XX_ENET - This driver supports the ethernet MACs in the Broadcom 63xx - MIPS chipset family (BCM63XX). - -+config BCM6368_ENETSW -+ tristate "Broadcom BCM6368 internal mac support" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ default y -+ help -+ This driver supports Ethernet controller integrated into Broadcom -+ BCM6368 family SoCs. -+ - config BCMGENET - tristate "Broadcom GENET internal MAC support" - depends on HAS_IOMEM ---- a/drivers/net/ethernet/broadcom/Makefile -+++ b/drivers/net/ethernet/broadcom/Makefile -@@ -6,6 +6,7 @@ - obj-$(CONFIG_B44) += b44.o - obj-$(CONFIG_BCM4908_ENET) += bcm4908_enet.o - obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o -+obj-$(CONFIG_BCM6368_ENETSW) += bcm6368-enetsw.o - obj-$(CONFIG_BCMGENET) += genet/ - obj-$(CONFIG_BNX2) += bnx2.o - obj-$(CONFIG_CNIC) += cnic.o diff --git a/target/linux/bmips/patches-5.15/501-net-broadcom-add-BCM6348-enet-controller-driver.patch b/target/linux/bmips/patches-5.15/501-net-broadcom-add-BCM6348-enet-controller-driver.patch deleted file mode 100644 index af09f4dd4f..0000000000 --- a/target/linux/bmips/patches-5.15/501-net-broadcom-add-BCM6348-enet-controller-driver.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 590b60fb08cb1e70fe02d3f407c6b3dbe9ad06ff Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Mon, 1 Mar 2021 07:34:39 +0100 -Subject: [PATCH] net: broadcom: add BCM6348 enetsw controller driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This controller is present on BCM6338, BCM6348 and BCM6358 SoCs. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/net/ethernet/broadcom/Kconfig | 8 ++++++++ - drivers/net/ethernet/broadcom/Makefile | 1 + - 2 files changed, 9 insertions(+) - ---- a/drivers/net/ethernet/broadcom/Kconfig -+++ b/drivers/net/ethernet/broadcom/Kconfig -@@ -68,6 +68,14 @@ config BCM63XX_ENET - This driver supports the ethernet MACs in the Broadcom 63xx - MIPS chipset family (BCM63XX). - -+config BCM6348_ENET -+ tristate "Broadcom BCM6348 internal mac support" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ default y -+ help -+ This driver supports Ethernet controller integrated into Broadcom -+ BCM6348 family SoCs. -+ - config BCM6368_ENETSW - tristate "Broadcom BCM6368 internal mac support" - depends on BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/net/ethernet/broadcom/Makefile -+++ b/drivers/net/ethernet/broadcom/Makefile -@@ -6,6 +6,7 @@ - obj-$(CONFIG_B44) += b44.o - obj-$(CONFIG_BCM4908_ENET) += bcm4908_enet.o - obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o -+obj-$(CONFIG_BCM6348_ENET) += bcm6348-enet.o - obj-$(CONFIG_BCM6368_ENETSW) += bcm6368-enetsw.o - obj-$(CONFIG_BCMGENET) += genet/ - obj-$(CONFIG_BNX2) += bnx2.o diff --git a/target/linux/bmips/patches-5.15/502-net-mdio-mux-bcm6368-allow-disabling.patch b/target/linux/bmips/patches-5.15/502-net-mdio-mux-bcm6368-allow-disabling.patch deleted file mode 100644 index 6071bea42d..0000000000 --- a/target/linux/bmips/patches-5.15/502-net-mdio-mux-bcm6368-allow-disabling.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 21145a89c79a22c4fb719cce5a2f4e3373d39756 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:16:46 +0200 -Subject: [PATCH] net: mdio: mux-bcm6368: allow disabling for bmips -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/net/mdio/Kconfig | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/net/mdio/Kconfig -+++ b/drivers/net/mdio/Kconfig -@@ -219,7 +219,6 @@ config MDIO_BUS_MUX_BCM6368 - tristate "Broadcom BCM6368 MDIO bus multiplexers" - depends on OF && OF_MDIO && (BMIPS_GENERIC || COMPILE_TEST) - select MDIO_BUS_MUX -- default BMIPS_GENERIC - help - This module provides a driver for MDIO bus multiplexers found in - BCM6368 based Broadcom SoCs. This multiplexer connects one of several diff --git a/target/linux/bmips/patches-5.15/600-mips-bmips-add-pci-support.patch b/target/linux/bmips/patches-5.15/600-mips-bmips-add-pci-support.patch deleted file mode 100644 index 2f19d1e489..0000000000 --- a/target/linux/bmips/patches-5.15/600-mips-bmips-add-pci-support.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 7742c1ba191a005a1356ff89b5fe2279d6f0ec4d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:18:43 +0200 -Subject: [PATCH] mips: bmips: add PCI support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/Kconfig | 1 + - arch/mips/pci/Makefile | 1 + - 2 files changed, 2 insertions(+) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -276,6 +276,7 @@ config BMIPS_GENERIC - select SYNC_R4K - select COMMON_CLK - select BCM6345_L1_IRQ -+ select HAVE_PCI - select IRQ_MIPS_CPU - select DMA_NONCOHERENT - select SYS_SUPPORTS_32BIT_KERNEL ---- a/arch/mips/pci/Makefile -+++ b/arch/mips/pci/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xt - # These are still pretty much in the old state, watch, go blind. - # - obj-$(CONFIG_ATH79) += fixup-ath79.o -+obj-$(CONFIG_BMIPS_GENERIC) += fixup-bmips.o - obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o - obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o - obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o diff --git a/target/linux/bmips/patches-5.15/601-pci-controllers-add-bcm6328-pcie-support.patch b/target/linux/bmips/patches-5.15/601-pci-controllers-add-bcm6328-pcie-support.patch deleted file mode 100644 index c976430fd5..0000000000 --- a/target/linux/bmips/patches-5.15/601-pci-controllers-add-bcm6328-pcie-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 49133041e0a5770decf1a25f575764d13a0d425c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:20:10 +0200 -Subject: [PATCH] pci: add bcm6328-pcie support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/pci/controller/Kconfig | 5 +++++ - drivers/pci/controller/Makefile | 1 + - 2 files changed, 6 insertions(+) - ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -3,6 +3,11 @@ - menu "PCI controller drivers" - depends on PCI - -+config PCIE_BCM6328 -+ bool "BCM6328 PCIe controller" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ depends on OF -+ - config PCI_MVEBU - bool "Marvell EBU PCIe controller" - depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -1,4 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o - obj-$(CONFIG_PCIE_CADENCE) += cadence/ - obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o - obj-$(CONFIG_PCI_IXP4XX) += pci-ixp4xx.o diff --git a/target/linux/bmips/patches-5.15/602-pci-controllers-add-bcm6318-pcie-support.patch b/target/linux/bmips/patches-5.15/602-pci-controllers-add-bcm6318-pcie-support.patch deleted file mode 100644 index 1a3ec1db2a..0000000000 --- a/target/linux/bmips/patches-5.15/602-pci-controllers-add-bcm6318-pcie-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cc3c30bdc98eabbaa07c64302eb5124a0f4a74f0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:20:46 +0200 -Subject: [PATCH] pci: add bcm6318-pcie support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/pci/controller/Kconfig | 5 +++++ - drivers/pci/controller/Makefile | 1 + - 2 files changed, 6 insertions(+) - ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -3,6 +3,11 @@ - menu "PCI controller drivers" - depends on PCI - -+config PCIE_BCM6318 -+ bool "BCM6318 PCIe controller" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ depends on OF -+ - config PCIE_BCM6328 - bool "BCM6328 PCIe controller" - depends on BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -1,4 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o - obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o - obj-$(CONFIG_PCIE_CADENCE) += cadence/ - obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o diff --git a/target/linux/bmips/patches-5.15/603-pci-controllers-add-bcm6348-pci-support.patch b/target/linux/bmips/patches-5.15/603-pci-controllers-add-bcm6348-pci-support.patch deleted file mode 100644 index 32aeea6a74..0000000000 --- a/target/linux/bmips/patches-5.15/603-pci-controllers-add-bcm6348-pci-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 5e7813e5725d79d00e0988472c306490fc48b3e1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:21:19 +0200 -Subject: [PATCH] pci: add bcm6348-pci support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/pci/controller/Kconfig | 5 +++++ - drivers/pci/controller/Makefile | 1 + - 2 files changed, 6 insertions(+) - ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -3,6 +3,11 @@ - menu "PCI controller drivers" - depends on PCI - -+config PCI_BCM6348 -+ bool "BCM6348 PCI controller" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ depends on OF -+ - config PCIE_BCM6318 - bool "BCM6318 PCIe controller" - depends on BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -1,4 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_PCI_BCM6348) += pci-bcm6348.o - obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o - obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o - obj-$(CONFIG_PCIE_CADENCE) += cadence/ diff --git a/target/linux/bmips/patches-5.15/700-leds-add-support-for-Sercomm-MSP430-LED-controller.patch b/target/linux/bmips/patches-5.15/700-leds-add-support-for-Sercomm-MSP430-LED-controller.patch deleted file mode 100644 index c6d2df9f8c..0000000000 --- a/target/linux/bmips/patches-5.15/700-leds-add-support-for-Sercomm-MSP430-LED-controller.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 1a5f2263d388016c88d39e141c7eb8085c9313fc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 5 Apr 2023 08:07:00 +0200 -Subject: [PATCH] leds: add support for Sercomm MSP430 LED controller -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Sercomm added an external MSP430G2513 for controlling LEDs through SPI on some -boards. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/leds/Kconfig | 9 +++++++++ - drivers/leds/Makefile | 1 + - 2 files changed, 10 insertions(+) - ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -289,6 +289,15 @@ config LEDS_COBALT_RAQ - help - This option enables support for the Cobalt Raq series LEDs. - -+config LEDS_SERCOMM_MSP430 -+ tristate "LED support for Sercomm MSP430 SPI LED controllers" -+ depends on LEDS_CLASS -+ depends on SPI -+ depends on OF -+ help -+ This option enables support for the Sercomm MSP430G2513 SPI LED -+ controllers. -+ - config LEDS_SUNFIRE - tristate "LED support for SunFire servers." - depends on LEDS_CLASS ---- a/drivers/leds/Makefile -+++ b/drivers/leds/Makefile -@@ -77,6 +77,7 @@ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o - obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o - obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o - obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o -+obj-$(CONFIG_LEDS_SERCOMM_MSP430) += leds-sercomm-msp430.o - obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o - obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o - obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o diff --git a/target/linux/bmips/patches-5.15/800-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch b/target/linux/bmips/patches-5.15/800-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch deleted file mode 100644 index d98d27c6b4..0000000000 --- a/target/linux/bmips/patches-5.15/800-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch +++ /dev/null @@ -1,26 +0,0 @@ -From ff3409ab17d56450943364ba49a16960e3cdda9b Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Sun, 6 Apr 2014 22:33:16 +0200 -Subject: [RFC] jffs2: work around unaligned accesses failing on bcm63xx/smp - -Unligned memcpy_fromio randomly fails with an unaligned dst. Work around -it by ensuring we are always doing aligned copies. - -Should fix filename corruption in jffs2 with SMP. - -Signed-off-by: Jonas Gorski ---- - fs/jffs2/nodelist.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/jffs2/nodelist.h -+++ b/fs/jffs2/nodelist.h -@@ -259,7 +259,7 @@ struct jffs2_full_dirent - uint32_t ino; /* == zero for unlink */ - unsigned int nhash; - unsigned char type; -- unsigned char name[]; -+ unsigned char name[] __attribute__((aligned((sizeof(long))))); - }; - - /* diff --git a/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch b/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch index 902bf4c68f..1ee4f27c46 100644 --- a/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch +++ b/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch @@ -104,7 +104,7 @@ Signed-off-by: Greg Kroah-Hartman +obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o --- a/drivers/usb/host/fotg210-hcd.c +++ /dev/null -@@ -1,5727 +0,0 @@ +@@ -1,5724 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Faraday FOTG210 EHCI-like driver - * @@ -536,8 +536,6 @@ Signed-off-by: Greg Kroah-Hartman - temp = size; - size -= temp; - next += temp; -- if (temp == size) -- goto done; - } - - temp = snprintf(next, size, "\n"); @@ -547,7 +545,6 @@ Signed-off-by: Greg Kroah-Hartman - size -= temp; - next += temp; - --done: - *sizep = size; - *nextp = next; -} diff --git a/target/linux/generic/backport-5.15/731-v6.1-0001-net-phy-Introduce-QUSGMII-PHY-mode.patch b/target/linux/generic/backport-5.15/731-v6.1-0001-net-phy-Introduce-QUSGMII-PHY-mode.patch new file mode 100644 index 0000000000..40b14fc36a --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0001-net-phy-Introduce-QUSGMII-PHY-mode.patch @@ -0,0 +1,99 @@ +From 5e61fe157a27afc7c0d4f7bcbceefdca536c015f Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Wed, 17 Aug 2022 14:32:52 +0200 +Subject: [PATCH] net: phy: Introduce QUSGMII PHY mode + +The QUSGMII mode is a derivative of Cisco's USXGMII standard. This +standard is pretty similar to SGMII, but allows for faster speeds, and +has the build-in bits for Quad and Octa variants (like QSGMII). + +The main difference with SGMII/QSGMII is that USXGMII/QUSGMII re-uses +the preamble to carry various information, named 'Extensions'. + +As of today, the USXGMII standard only mentions the "PCH" extension, +which is used to convey timestamps, allowing in-band signaling of PTP +timestamps without having to modify the frame itself. + +This commit adds support for that mode. When no extension is in use, it +behaves exactly like QSGMII, although it's not compatible with QSGMII. + +Signed-off-by: Maxime Chevallier +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 9 +++++++++ + drivers/net/phy/phylink.c | 3 +++ + include/linux/phy.h | 4 ++++ + 3 files changed, 16 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -303,6 +303,15 @@ Some of the interface modes are describe + rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying + data rate of 100Mpbs. + ++``PHY_INTERFACE_MODE_QUSGMII`` ++ This defines the Cisco the Quad USGMII mode, which is the Quad variant of ++ the USGMII (Universal SGMII) link. It's very similar to QSGMII, but uses ++ a Packet Control Header (PCH) instead of the 7 bytes preamble to carry not ++ only the port id, but also so-called "extensions". The only documented ++ extension so-far in the specification is the inclusion of timestamps, for ++ PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the ++ same capabilities in terms of link speed and negociation. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -367,6 +367,7 @@ void phylink_get_linkmodes(unsigned long + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_GMII: + caps |= MAC_1000HD | MAC_1000FD; +@@ -630,6 +631,7 @@ static int phylink_parse_mode(struct phy + switch (pl->link_config.interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: + phylink_set(pl->supported, 10baseT_Half); + phylink_set(pl->supported, 10baseT_Full); + phylink_set(pl->supported, 100baseT_Half); +@@ -2956,6 +2958,7 @@ void phylink_mii_c22_pcs_get_state(struc + + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: + phylink_decode_sgmii_word(state, lpa); + break; + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -115,6 +115,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_25GBASER: 25G BaseR + * @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII + * @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN ++ * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII + * @PHY_INTERFACE_MODE_MAX: Book keeping + * + * Describes the interface between the MAC and PHY. +@@ -152,6 +153,7 @@ typedef enum { + PHY_INTERFACE_MODE_USXGMII, + /* 10GBASE-KR - with Clause 73 AN */ + PHY_INTERFACE_MODE_10GKR, ++ PHY_INTERFACE_MODE_QUSGMII, + PHY_INTERFACE_MODE_MAX, + } phy_interface_t; + +@@ -267,6 +269,8 @@ static inline const char *phy_modes(phy_ + return "10gbase-kr"; + case PHY_INTERFACE_MODE_100BASEX: + return "100base-x"; ++ case PHY_INTERFACE_MODE_QUSGMII: ++ return "qusgmii"; + default: + return "unknown"; + } diff --git a/target/linux/generic/backport-5.15/731-v6.1-0002-net-phy-Add-helper-to-derive-the-number-of-ports-fro.patch b/target/linux/generic/backport-5.15/731-v6.1-0002-net-phy-Add-helper-to-derive-the-number-of-ports-fro.patch new file mode 100644 index 0000000000..a9706af893 --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0002-net-phy-Add-helper-to-derive-the-number-of-ports-fro.patch @@ -0,0 +1,93 @@ +From c04ade27cb7b952b6b9b9a0efa0a6129cc63f2ae Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Wed, 17 Aug 2022 14:32:54 +0200 +Subject: [PATCH] net: phy: Add helper to derive the number of ports from a phy + mode + +Some phy modes such as QSGMII multiplex several MAC<->PHY links on one +single physical interface. QSGMII used to be the only one supported, but +other modes such as QUSGMII also carry multiple links. + +This helper allows getting the number of links that are multiplexed +on a given interface. + +Signed-off-by: Maxime Chevallier +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy-core.c | 52 ++++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 2 ++ + 2 files changed, 54 insertions(+) + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -74,6 +74,58 @@ const char *phy_duplex_to_str(unsigned i + } + EXPORT_SYMBOL_GPL(phy_duplex_to_str); + ++/** ++ * phy_interface_num_ports - Return the number of links that can be carried by ++ * a given MAC-PHY physical link. Returns 0 if this is ++ * unknown, the number of links else. ++ * ++ * @interface: The interface mode we want to get the number of ports ++ */ ++int phy_interface_num_ports(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_NA: ++ return 0; ++ case PHY_INTERFACE_MODE_INTERNAL: ++ case PHY_INTERFACE_MODE_MII: ++ case PHY_INTERFACE_MODE_GMII: ++ case PHY_INTERFACE_MODE_TBI: ++ case PHY_INTERFACE_MODE_REVMII: ++ case PHY_INTERFACE_MODE_RMII: ++ case PHY_INTERFACE_MODE_REVRMII: ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RTBI: ++ case PHY_INTERFACE_MODE_XGMII: ++ case PHY_INTERFACE_MODE_XLGMII: ++ case PHY_INTERFACE_MODE_MOCA: ++ case PHY_INTERFACE_MODE_TRGMII: ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_SMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_25GBASER: ++ case PHY_INTERFACE_MODE_10GKR: ++ case PHY_INTERFACE_MODE_100BASEX: ++ case PHY_INTERFACE_MODE_RXAUI: ++ case PHY_INTERFACE_MODE_XAUI: ++ return 1; ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: ++ return 4; ++ case PHY_INTERFACE_MODE_MAX: ++ WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); ++ return 0; ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(phy_interface_num_ports); ++ + /* A mapping of all SUPPORTED settings to speed/duplex. This table + * must be grouped by speed and sorted in descending match priority + * - iow, descending speed. +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -964,6 +964,8 @@ struct phy_fixup { + const char *phy_speed_to_str(int speed); + const char *phy_duplex_to_str(unsigned int duplex); + ++int phy_interface_num_ports(phy_interface_t interface); ++ + /* A structure for mapping a particular speed and duplex + * combination to a particular SUPPORTED and ADVERTISED value + */ diff --git a/target/linux/generic/backport-5.15/731-v6.1-0003-net-phy-Add-1000BASE-KX-interface-mode.patch b/target/linux/generic/backport-5.15/731-v6.1-0003-net-phy-Add-1000BASE-KX-interface-mode.patch new file mode 100644 index 0000000000..70669dde3a --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0003-net-phy-Add-1000BASE-KX-interface-mode.patch @@ -0,0 +1,96 @@ +From 05ad5d4581c3c1cc724fe50d4652833fb9f3037b Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Fri, 2 Sep 2022 18:02:39 -0400 +Subject: [PATCH] net: phy: Add 1000BASE-KX interface mode + +Add 1000BASE-KX interface mode. This 1G backplane ethernet as described in +clause 70. Clause 73 autonegotiation is mandatory, and only full duplex +operation is supported. + +Although at the PMA level this interface mode is identical to +1000BASE-X, it uses a different form of in-band autonegation. This +justifies a separate interface mode, since the interface mode (along +with the MLO_AN_* autonegotiation mode) sets the type of autonegotiation +which will be used on a link. This results in more than just electrical +differences between the link modes. + +With regard to 1000BASE-X, 1000BASE-KX holds a similar position to +SGMII: same signaling, but different autonegotiation. PCS drivers +(which typically handle in-band autonegotiation) may only support +1000BASE-X, and not 1000BASE-KX. Similarly, the phy mode is used to +configure serdes phys with phy_set_mode_ext. Due to the different +electrical standards (SFI or XFI vs Clause 70), they will likely want to +use different configuration. Adding a phy interface mode for +1000BASE-KX helps simplify configuration in these areas. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 6 ++++++ + drivers/net/phy/phy-core.c | 1 + + drivers/net/phy/phylink.c | 1 + + include/linux/phy.h | 4 ++++ + 4 files changed, 12 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -312,6 +312,12 @@ Some of the interface modes are describe + PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the + same capabilities in terms of link speed and negociation. + ++``PHY_INTERFACE_MODE_1000BASEKX`` ++ This is 1000BASE-X as defined by IEEE 802.3 Clause 36 with Clause 73 ++ autonegotiation. Generally, it will be used with a Clause 70 PMD. To ++ contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this ++ interface mode has different autonegotiation and only supports full duplex. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -114,6 +114,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_100BASEX: + case PHY_INTERFACE_MODE_RXAUI: + case PHY_INTERFACE_MODE_XAUI: ++ case PHY_INTERFACE_MODE_1000BASEKX: + return 1; + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -390,6 +390,7 @@ void phylink_get_linkmodes(unsigned long + case PHY_INTERFACE_MODE_1000BASEX: + caps |= MAC_1000HD; + fallthrough; ++ case PHY_INTERFACE_MODE_1000BASEKX: + case PHY_INTERFACE_MODE_TRGMII: + caps |= MAC_1000FD; + break; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -116,6 +116,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII + * @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN + * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII ++ * @PHY_INTERFACE_MODE_1000BASEKX: 1000Base-KX - with Clause 73 AN + * @PHY_INTERFACE_MODE_MAX: Book keeping + * + * Describes the interface between the MAC and PHY. +@@ -154,6 +155,7 @@ typedef enum { + /* 10GBASE-KR - with Clause 73 AN */ + PHY_INTERFACE_MODE_10GKR, + PHY_INTERFACE_MODE_QUSGMII, ++ PHY_INTERFACE_MODE_1000BASEKX, + PHY_INTERFACE_MODE_MAX, + } phy_interface_t; + +@@ -251,6 +253,8 @@ static inline const char *phy_modes(phy_ + return "trgmii"; + case PHY_INTERFACE_MODE_1000BASEX: + return "1000base-x"; ++ case PHY_INTERFACE_MODE_1000BASEKX: ++ return "1000base-kx"; + case PHY_INTERFACE_MODE_2500BASEX: + return "2500base-x"; + case PHY_INTERFACE_MODE_5GBASER: diff --git a/target/linux/generic/backport-5.15/731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch b/target/linux/generic/backport-5.15/731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch new file mode 100644 index 0000000000..fc02d7a4ea --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch @@ -0,0 +1,294 @@ +From 0c3e10cb44232833a50cb8e3e784c432906a60c1 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Tue, 20 Sep 2022 18:12:31 -0400 +Subject: [PATCH] net: phy: Add support for rate matching + +This adds support for rate matching (also known as rate adaptation) to +the phy subsystem. The general idea is that the phy interface runs at +one speed, and the MAC throttles the rate at which it sends packets to +the link speed. There's a good overview of several techniques for +achieving this at [1]. This patch adds support for three: pause-frame +based (such as in Aquantia phys), CRS-based (such as in 10PASS-TS and +2BASE-TL), and open-loop-based (such as in 10GBASE-W). + +This patch makes a few assumptions and a few non assumptions about the +types of rate matching available. First, it assumes that different phys +may use different forms of rate matching. Second, it assumes that phys +can use rate matching for any of their supported link speeds (e.g. if a +phy supports 10BASE-T and XGMII, then it can adapt XGMII to 10BASE-T). +Third, it does not assume that all interface modes will use the same +form of rate matching. Fourth, it does not assume that all phy devices +will support rate matching (even if some do). Relaxing or strengthening +these (non-)assumptions could result in a different API. For example, if +all interface modes were assumed to use the same form of rate matching, +then a bitmask of interface modes supportting rate matching would +suffice. + +For some better visibility into the process, the current rate matching +mode is exposed as part of the ethtool ksettings. For the moment, only +read access is supported. I'm not sure what userspace might want to +configure yet (disable it altogether, disable just one mode, specify the +mode to use, etc.). For the moment, since only pause-based rate +adaptation support is added in the next few commits, rate matching can +be disabled altogether by adjusting the advertisement. + +802.3 calls this feature "rate adaptation" in clause 49 (10GBASE-R) and +"rate matching" in clause 61 (10PASS-TL and 2BASE-TS). Aquantia also calls +this feature "rate adaptation". I chose "rate matching" because it is +shorter, and because Russell doesn't think "adaptation" is correct in this +context. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + Documentation/networking/ethtool-netlink.rst | 2 ++ + drivers/net/phy/phy-core.c | 21 +++++++++++++++ + drivers/net/phy/phy.c | 28 ++++++++++++++++++++ + include/linux/phy.h | 22 ++++++++++++++- + include/uapi/linux/ethtool.h | 18 +++++++++++-- + include/uapi/linux/ethtool_netlink.h | 1 + + net/ethtool/ioctl.c | 1 + + net/ethtool/linkmodes.c | 5 ++++ + 8 files changed, 95 insertions(+), 3 deletions(-) + +--- a/Documentation/networking/ethtool-netlink.rst ++++ b/Documentation/networking/ethtool-netlink.rst +@@ -418,6 +418,7 @@ Kernel response contents: + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE`` u8 Master/slave port state ++ ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching + ========================================== ====== ========================== + + For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask +@@ -441,6 +442,7 @@ Request contents: + ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode ++ ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching + ``ETHTOOL_A_LINKMODES_LANES`` u32 lanes + ========================================== ====== ========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -75,6 +75,27 @@ const char *phy_duplex_to_str(unsigned i + EXPORT_SYMBOL_GPL(phy_duplex_to_str); + + /** ++ * phy_rate_matching_to_str - Return a string describing the rate matching ++ * ++ * @rate_matching: Type of rate matching to describe ++ */ ++const char *phy_rate_matching_to_str(int rate_matching) ++{ ++ switch (rate_matching) { ++ case RATE_MATCH_NONE: ++ return "none"; ++ case RATE_MATCH_PAUSE: ++ return "pause"; ++ case RATE_MATCH_CRS: ++ return "crs"; ++ case RATE_MATCH_OPEN_LOOP: ++ return "open-loop"; ++ } ++ return "Unsupported (update phy-core.c)"; ++} ++EXPORT_SYMBOL_GPL(phy_rate_matching_to_str); ++ ++/** + * phy_interface_num_ports - Return the number of links that can be carried by + * a given MAC-PHY physical link. Returns 0 if this is + * unknown, the number of links else. +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -127,6 +127,33 @@ void phy_print_status(struct phy_device + EXPORT_SYMBOL(phy_print_status); + + /** ++ * phy_get_rate_matching - determine if rate matching is supported ++ * @phydev: The phy device to return rate matching for ++ * @iface: The interface mode to use ++ * ++ * This determines the type of rate matching (if any) that @phy supports ++ * using @iface. @iface may be %PHY_INTERFACE_MODE_NA to determine if any ++ * interface supports rate matching. ++ * ++ * Return: The type of rate matching @phy supports for @iface, or ++ * %RATE_MATCH_NONE. ++ */ ++int phy_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ int ret = RATE_MATCH_NONE; ++ ++ if (phydev->drv->get_rate_matching) { ++ mutex_lock(&phydev->lock); ++ ret = phydev->drv->get_rate_matching(phydev, iface); ++ mutex_unlock(&phydev->lock); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(phy_get_rate_matching); ++ ++/** + * phy_config_interrupt - configure the PHY device for the requested interrupts + * @phydev: the phy_device struct + * @interrupts: interrupt flags to configure for this @phydev +@@ -268,6 +295,7 @@ void phy_ethtool_ksettings_get(struct ph + cmd->base.duplex = phydev->duplex; + cmd->base.master_slave_cfg = phydev->master_slave_get; + cmd->base.master_slave_state = phydev->master_slave_state; ++ cmd->base.rate_matching = phydev->rate_matching; + if (phydev->interface == PHY_INTERFACE_MODE_MOCA) + cmd->base.port = PORT_BNC; + else +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -280,7 +280,6 @@ static inline const char *phy_modes(phy_ + } + } + +- + #define PHY_INIT_TIMEOUT 100000 + #define PHY_FORCE_TIMEOUT 10 + +@@ -573,6 +572,7 @@ struct macsec_ops; + * @lp_advertising: Current link partner advertised linkmodes + * @eee_broken_modes: Energy efficient ethernet modes which should be prohibited + * @autoneg: Flag autoneg being used ++ * @rate_matching: Current rate matching mode + * @link: Current link state + * @autoneg_complete: Flag auto negotiation of the link has completed + * @mdix: Current crossover +@@ -639,6 +639,8 @@ struct phy_device { + unsigned irq_suspended:1; + unsigned irq_rerun:1; + ++ int rate_matching; ++ + enum phy_state state; + + u32 dev_flags; +@@ -801,6 +803,21 @@ struct phy_driver { + */ + int (*get_features)(struct phy_device *phydev); + ++ /** ++ * @get_rate_matching: Get the supported type of rate matching for a ++ * particular phy interface. This is used by phy consumers to determine ++ * whether to advertise lower-speed modes for that interface. It is ++ * assumed that if a rate matching mode is supported on an interface, ++ * then that interface's rate can be adapted to all slower link speeds ++ * supported by the phy. If iface is %PHY_INTERFACE_MODE_NA, and the phy ++ * supports any kind of rate matching for any interface, then it must ++ * return that rate matching mode (preferring %RATE_MATCH_PAUSE to ++ * %RATE_MATCH_CRS). If the interface is not supported, this should ++ * return %RATE_MATCH_NONE. ++ */ ++ int (*get_rate_matching)(struct phy_device *phydev, ++ phy_interface_t iface); ++ + /* PHY Power Management */ + /** @suspend: Suspend the hardware, saving state if needed */ + int (*suspend)(struct phy_device *phydev); +@@ -967,6 +984,7 @@ struct phy_fixup { + + const char *phy_speed_to_str(int speed); + const char *phy_duplex_to_str(unsigned int duplex); ++const char *phy_rate_matching_to_str(int rate_matching); + + int phy_interface_num_ports(phy_interface_t interface); + +@@ -1675,6 +1693,8 @@ int phy_disable_interrupts(struct phy_de + void phy_request_interrupt(struct phy_device *phydev); + void phy_free_interrupt(struct phy_device *phydev); + void phy_print_status(struct phy_device *phydev); ++int phy_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface); + int phy_set_max_speed(struct phy_device *phydev, u32 max_speed); + void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode); + void phy_advertise_supported(struct phy_device *phydev); +--- a/include/uapi/linux/ethtool.h ++++ b/include/uapi/linux/ethtool.h +@@ -1809,6 +1809,20 @@ static inline int ethtool_validate_duple + #define MASTER_SLAVE_STATE_SLAVE 3 + #define MASTER_SLAVE_STATE_ERR 4 + ++/* These are used to throttle the rate of data on the phy interface when the ++ * native speed of the interface is higher than the link speed. These should ++ * not be used for phy interfaces which natively support multiple speeds (e.g. ++ * MII or SGMII). ++ */ ++/* No rate matching performed. */ ++#define RATE_MATCH_NONE 0 ++/* The phy sends pause frames to throttle the MAC. */ ++#define RATE_MATCH_PAUSE 1 ++/* The phy asserts CRS to prevent the MAC from transmitting. */ ++#define RATE_MATCH_CRS 2 ++/* The MAC is programmed with a sufficiently-large IPG. */ ++#define RATE_MATCH_OPEN_LOOP 3 ++ + /* Which connector port. */ + #define PORT_TP 0x00 + #define PORT_AUI 0x01 +@@ -2002,8 +2016,8 @@ enum ethtool_reset_flags { + * reported consistently by PHYLIB. Read-only. + * @master_slave_cfg: Master/slave port mode. + * @master_slave_state: Master/slave port state. ++ * @rate_matching: Rate adaptation performed by the PHY + * @reserved: Reserved for future use; see the note on reserved space. +- * @reserved1: Reserved for future use; see the note on reserved space. + * @link_mode_masks: Variable length bitmaps. + * + * If autonegotiation is disabled, the speed and @duplex represent the +@@ -2054,7 +2068,7 @@ struct ethtool_link_settings { + __u8 transceiver; + __u8 master_slave_cfg; + __u8 master_slave_state; +- __u8 reserved1[1]; ++ __u8 rate_matching; + __u32 reserved[7]; + __u32 link_mode_masks[0]; + /* layout of link_mode_masks fields: +--- a/include/uapi/linux/ethtool_netlink.h ++++ b/include/uapi/linux/ethtool_netlink.h +@@ -238,6 +238,7 @@ enum { + ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */ + ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */ + ETHTOOL_A_LINKMODES_LANES, /* u32 */ ++ ETHTOOL_A_LINKMODES_RATE_MATCHING, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_LINKMODES_CNT, +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -559,6 +559,7 @@ static int ethtool_get_link_ksettings(st + = __ETHTOOL_LINK_MODE_MASK_NU32; + link_ksettings.base.master_slave_cfg = MASTER_SLAVE_CFG_UNSUPPORTED; + link_ksettings.base.master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; ++ link_ksettings.base.rate_matching = RATE_MATCH_NONE; + + return store_link_ksettings_for_user(useraddr, &link_ksettings); + } +--- a/net/ethtool/linkmodes.c ++++ b/net/ethtool/linkmodes.c +@@ -70,6 +70,7 @@ static int linkmodes_reply_size(const st + + nla_total_size(sizeof(u32)) /* LINKMODES_SPEED */ + + nla_total_size(sizeof(u32)) /* LINKMODES_LANES */ + + nla_total_size(sizeof(u8)) /* LINKMODES_DUPLEX */ ++ + nla_total_size(sizeof(u8)) /* LINKMODES_RATE_MATCHING */ + + 0; + ret = ethnl_bitset_size(ksettings->link_modes.advertising, + ksettings->link_modes.supported, +@@ -143,6 +144,10 @@ static int linkmodes_fill_reply(struct s + lsettings->master_slave_state)) + return -EMSGSIZE; + ++ if (nla_put_u8(skb, ETHTOOL_A_LINKMODES_RATE_MATCHING, ++ lsettings->rate_matching)) ++ return -EMSGSIZE; ++ + return 0; + } + diff --git a/target/linux/generic/backport-5.15/735-v6.0-0001-net-phy-Add-support-for-AQR113C-EPHY.patch b/target/linux/generic/backport-5.15/735-v6.0-0001-net-phy-Add-support-for-AQR113C-EPHY.patch new file mode 100644 index 0000000000..6090a40eae --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v6.0-0001-net-phy-Add-support-for-AQR113C-EPHY.patch @@ -0,0 +1,58 @@ +From 12cf1b89a66828719b2135891b65bd5d03eedea9 Mon Sep 17 00:00:00 2001 +From: Bhadram Varka +Date: Tue, 21 Jun 2022 09:10:27 +0530 +Subject: [PATCH] net: phy: Add support for AQR113C EPHY + +Add support multi-gigabit and single-port Ethernet +PHY transceiver (AQR113C). + +Signed-off-by: Bhadram Varka +Link: https://lore.kernel.org/r/20220621034027.56508-1-vbhadram@nvidia.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/aquantia_main.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -22,6 +22,7 @@ + #define PHY_ID_AQR107 0x03a1b4e0 + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR113C 0x31c31c12 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -744,6 +745,24 @@ static struct phy_driver aqr_driver[] = + .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr_read_status, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), ++ .name = "Aquantia AQR113C", ++ .probe = aqr107_probe, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -756,6 +775,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { } + }; + diff --git a/target/linux/generic/backport-5.15/736-v6.1-0001-net-phy-aquantia-Add-some-additional-phy-interfaces.patch b/target/linux/generic/backport-5.15/736-v6.1-0001-net-phy-aquantia-Add-some-additional-phy-interfaces.patch new file mode 100644 index 0000000000..ec8485e0a7 --- /dev/null +++ b/target/linux/generic/backport-5.15/736-v6.1-0001-net-phy-aquantia-Add-some-additional-phy-interfaces.patch @@ -0,0 +1,71 @@ +From 7de26bf144f6a72858ab60afb2bd2b43265ee0ad Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Tue, 20 Sep 2022 18:12:34 -0400 +Subject: [PATCH] net: phy: aquantia: Add some additional phy interfaces + +These are documented in the AQR115 register reference. I haven't tested +them, but perhaps they'll be useful to someone. + +Signed-off-by: Sean Anderson +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia_main.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -27,9 +27,12 @@ + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 + + #define MDIO_AN_VEND_PROV 0xc400 +@@ -401,15 +404,24 @@ static int aqr107_read_status(struct phy + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: + phydev->interface = PHY_INTERFACE_MODE_10GKR; + break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: ++ phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; ++ break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: + phydev->interface = PHY_INTERFACE_MODE_10GBASER; + break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: + phydev->interface = PHY_INTERFACE_MODE_USXGMII; + break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: ++ phydev->interface = PHY_INTERFACE_MODE_XAUI; ++ break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: + phydev->interface = PHY_INTERFACE_MODE_SGMII; + break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: ++ phydev->interface = PHY_INTERFACE_MODE_RXAUI; ++ break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: + phydev->interface = PHY_INTERFACE_MODE_2500BASEX; + break; +@@ -522,11 +534,14 @@ static int aqr107_config_init(struct phy + + /* Check that the PHY interface type is compatible */ + if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && + phydev->interface != PHY_INTERFACE_MODE_2500BASEX && + phydev->interface != PHY_INTERFACE_MODE_XGMII && + phydev->interface != PHY_INTERFACE_MODE_USXGMII && + phydev->interface != PHY_INTERFACE_MODE_10GKR && +- phydev->interface != PHY_INTERFACE_MODE_10GBASER) ++ phydev->interface != PHY_INTERFACE_MODE_10GBASER && ++ phydev->interface != PHY_INTERFACE_MODE_XAUI && ++ phydev->interface != PHY_INTERFACE_MODE_RXAUI) + return -ENODEV; + + WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, diff --git a/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch b/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch new file mode 100644 index 0000000000..d5d58762ce --- /dev/null +++ b/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch @@ -0,0 +1,148 @@ +From 3c42563b30417afc8855a3b4c1b38c2f36f78657 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Tue, 20 Sep 2022 18:12:35 -0400 +Subject: [PATCH] net: phy: aquantia: Add support for rate matching + +This adds support for rate matching for phys similar to the AQR107. We +assume that all phys using aqr107_read_status support rate matching. +However, it could be possible to determine support based on the firmware +revision if there are phys discovered which do not support rate +matching. However, as rate matching is advertised in the datasheets for +these phys, I suspect it is supported most boards. + +Despite the name, the "config" registers are updated with the current +rate matching method (if any). Because they appear to be updated +automatically, I don't know if these registers can be used to disable +rate matching. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia_main.c | 51 ++++++++++++++++++++++++++++++--- + 1 file changed, 47 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -97,6 +97,19 @@ + #define VEND1_GLOBAL_GEN_STAT2 0xc831 + #define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) + ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ + #define VEND1_GLOBAL_RSVD_STAT1 0xc885 + #define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) + #define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +@@ -347,40 +360,57 @@ static int aqr_read_status(struct phy_de + + static int aqr107_read_rate(struct phy_device *phydev) + { ++ u32 config_reg; + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); + if (val < 0) + return val; + ++ if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ + switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { + case MDIO_AN_TX_VEND_STATUS1_10BASET: + phydev->speed = SPEED_10; ++ config_reg = VEND1_GLOBAL_CFG_10M; + break; + case MDIO_AN_TX_VEND_STATUS1_100BASETX: + phydev->speed = SPEED_100; ++ config_reg = VEND1_GLOBAL_CFG_100M; + break; + case MDIO_AN_TX_VEND_STATUS1_1000BASET: + phydev->speed = SPEED_1000; ++ config_reg = VEND1_GLOBAL_CFG_1G; + break; + case MDIO_AN_TX_VEND_STATUS1_2500BASET: + phydev->speed = SPEED_2500; ++ config_reg = VEND1_GLOBAL_CFG_2_5G; + break; + case MDIO_AN_TX_VEND_STATUS1_5000BASET: + phydev->speed = SPEED_5000; ++ config_reg = VEND1_GLOBAL_CFG_5G; + break; + case MDIO_AN_TX_VEND_STATUS1_10GBASET: + phydev->speed = SPEED_10000; ++ config_reg = VEND1_GLOBAL_CFG_10G; + break; + default: + phydev->speed = SPEED_UNKNOWN; +- break; ++ return 0; + } + +- if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) +- phydev->duplex = DUPLEX_FULL; ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); ++ if (val < 0) ++ return val; ++ ++ if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == ++ VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) ++ phydev->rate_matching = RATE_MATCH_PAUSE; + else +- phydev->duplex = DUPLEX_HALF; ++ phydev->rate_matching = RATE_MATCH_NONE; + + return 0; + } +@@ -647,6 +677,16 @@ static int aqr107_wait_processor_intensi + return 0; + } + ++static int aqr107_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ if (iface == PHY_INTERFACE_MODE_10GBASER || ++ iface == PHY_INTERFACE_MODE_2500BASEX || ++ iface == PHY_INTERFACE_MODE_NA) ++ return RATE_MATCH_PAUSE; ++ return RATE_MATCH_NONE; ++} ++ + static int aqr107_suspend(struct phy_device *phydev) + { + int err; +@@ -720,6 +760,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQR107), + .name = "Aquantia AQR107", + .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, + .config_init = aqr107_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, +@@ -738,6 +779,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), + .name = "Aquantia AQCS109", + .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, + .config_init = aqcs109_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, +@@ -764,6 +806,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), + .name = "Aquantia AQR113C", + .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, + .config_init = aqr107_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, diff --git a/target/linux/generic/backport-5.15/737-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch b/target/linux/generic/backport-5.15/737-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch new file mode 100644 index 0000000000..4bb786e790 --- /dev/null +++ b/target/linux/generic/backport-5.15/737-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch @@ -0,0 +1,2310 @@ +From d2213db3f49bce8e7a87c8de05b9a091f78f654e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:41 +0100 +Subject: [PATCH 1/3] net: phy: aquantia: move to separate directory + +Move aquantia PHY driver to separate driectory in preparation for +firmware loading support to keep things tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 5 +---- + drivers/net/phy/Makefile | 6 +----- + drivers/net/phy/aquantia/Kconfig | 5 +++++ + drivers/net/phy/aquantia/Makefile | 6 ++++++ + drivers/net/phy/{ => aquantia}/aquantia.h | 0 + drivers/net/phy/{ => aquantia}/aquantia_hwmon.c | 0 + drivers/net/phy/{ => aquantia}/aquantia_main.c | 0 + 7 files changed, 13 insertions(+), 9 deletions(-) + create mode 100644 drivers/net/phy/aquantia/Kconfig + create mode 100644 drivers/net/phy/aquantia/Makefile + rename drivers/net/phy/{ => aquantia}/aquantia.h (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_hwmon.c (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_main.c (100%) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -83,10 +83,7 @@ config ADIN_PHY + - ADIN1300 - Robust,Industrial, Low Latency 10/100/1000 Gigabit + Ethernet PHY + +-config AQUANTIA_PHY +- tristate "Aquantia PHYs" +- help +- Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 ++source "drivers/net/phy/aquantia/Kconfig" + + config AX88796B_PHY + tristate "Asix PHYs" +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -32,11 +32,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_AMD_PHY) += amd.o +-aquantia-objs += aquantia_main.o +-ifdef CONFIG_HWMON +-aquantia-objs += aquantia_hwmon.o +-endif +-obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_BCM54140_PHY) += bcm54140.o +--- /dev/null ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config AQUANTIA_PHY ++ tristate "Aquantia PHYs" ++ help ++ Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- /dev/null ++++ b/drivers/net/phy/aquantia/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++aquantia-objs += aquantia_main.o ++ifdef CONFIG_HWMON ++aquantia-objs += aquantia_hwmon.o ++endif ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o +--- a/drivers/net/phy/aquantia.h ++++ /dev/null +@@ -1,16 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +- +-#if IS_REACHABLE(CONFIG_HWMON) +-int aqr_hwmon_probe(struct phy_device *phydev); +-#else +-static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } +-#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++int aqr_hwmon_probe(struct phy_device *phydev); ++#else ++static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -0,0 +1,250 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++ ++static umode_t aqr_hwmon_is_visible(const void *data, ++ enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ if (type != hwmon_temp) ++ return 0; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ case hwmon_temp_min_alarm: ++ case hwmon_temp_max_alarm: ++ case hwmon_temp_lcrit_alarm: ++ case hwmon_temp_crit_alarm: ++ return 0444; ++ case hwmon_temp_min: ++ case hwmon_temp_max: ++ case hwmon_temp_lcrit: ++ case hwmon_temp_crit: ++ return 0644; ++ default: ++ return 0; ++ } ++} ++ ++static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) ++{ ++ int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (temp < 0) ++ return temp; ++ ++ /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ ++ *value = (s16)temp * 1000 / 256; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) ++{ ++ int temp; ++ ++ if (value >= 128000 || value < -128000) ++ return -ERANGE; ++ ++ temp = value * 256 / 1000; ++ ++ /* temp is in s16 range and we're interested in lower 16 bits only */ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); ++} ++ ++static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) ++{ ++ int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (val < 0) ++ return val; ++ ++ return !!(val & bit); ++} ++ ++static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) ++{ ++ int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); ++ ++ if (val < 0) ++ return val; ++ ++ *value = val; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ int reg; ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, ++ VEND1_THERMAL_STAT2_VALID); ++ if (reg < 0) ++ return reg; ++ if (!reg) ++ return -EBUSY; ++ ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); ++ ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ case hwmon_temp_lcrit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static const struct hwmon_ops aqr_hwmon_ops = { ++ .is_visible = aqr_hwmon_is_visible, ++ .read = aqr_hwmon_read, ++ .write = aqr_hwmon_write, ++}; ++ ++static u32 aqr_hwmon_chip_config[] = { ++ HWMON_C_REGISTER_TZ, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_chip = { ++ .type = hwmon_chip, ++ .config = aqr_hwmon_chip_config, ++}; ++ ++static u32 aqr_hwmon_temp_config[] = { ++ HWMON_T_INPUT | ++ HWMON_T_MAX | HWMON_T_MIN | ++ HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | ++ HWMON_T_CRIT | HWMON_T_LCRIT | ++ HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_temp = { ++ .type = hwmon_temp, ++ .config = aqr_hwmon_temp_config, ++}; ++ ++static const struct hwmon_channel_info *aqr_hwmon_info[] = { ++ &aqr_hwmon_chip, ++ &aqr_hwmon_temp, ++ NULL, ++}; ++ ++static const struct hwmon_chip_info aqr_hwmon_chip_info = { ++ .ops = &aqr_hwmon_ops, ++ .info = aqr_hwmon_info, ++}; ++ ++int aqr_hwmon_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct device *hwmon_dev; ++ char *hwmon_name; ++ int i, j; ++ ++ hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); ++ if (!hwmon_name) ++ return -ENOMEM; ++ ++ for (i = j = 0; hwmon_name[i]; i++) { ++ if (isalnum(hwmon_name[i])) { ++ if (i != j) ++ hwmon_name[j] = hwmon_name[i]; ++ j++; ++ } ++ } ++ hwmon_name[j] = '\0'; ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, ++ phydev, &aqr_hwmon_chip_info, NULL); ++ ++ return PTR_ERR_OR_ZERO(hwmon_dev); ++} ++ ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -0,0 +1,844 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for Aquantia PHY ++ * ++ * Author: Shaohui Xie ++ * ++ * Copyright 2015 Freescale Semiconductor, Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++#define PHY_ID_AQ1202 0x03a1b445 ++#define PHY_ID_AQ2104 0x03a1b460 ++#define PHY_ID_AQR105 0x03a1b4a2 ++#define PHY_ID_AQR106 0x03a1b4d0 ++#define PHY_ID_AQR107 0x03a1b4e0 ++#define PHY_ID_AQCS109 0x03a1b5c2 ++#define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR113C 0x31c31c12 ++ ++#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 ++ ++#define MDIO_AN_VEND_PROV 0xc400 ++#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) ++#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) ++#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) ++#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 ++ ++#define MDIO_AN_TX_VEND_STATUS1 0xc800 ++#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) ++#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 ++#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 ++#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 ++#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 ++#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 ++#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 ++#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 ++#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 ++#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 ++#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) ++ ++#define MDIO_AN_RX_LP_STAT1 0xe820 ++#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) ++#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) ++#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) ++#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) ++#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) ++ ++#define MDIO_AN_RX_LP_STAT4 0xe823 ++#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) ++#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) ++ ++#define MDIO_AN_RX_VEND_STAT3 0xe832 ++#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) ++ ++/* MDIO_MMD_C22EXT */ ++#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 ++#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 ++#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 ++#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 ++#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 ++#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 ++#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 ++#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 ++#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a ++#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b ++ ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ ++/* Sleep and timeout for checking if the Processor-Intensive ++ * MDIO operation is finished ++ */ ++#define AQR107_OP_IN_PROG_SLEEP 1000 ++#define AQR107_OP_IN_PROG_TIMEOUT 100000 ++ ++struct aqr107_hw_stat { ++ const char *name; ++ int reg; ++ int size; ++}; ++ ++#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } ++static const struct aqr107_hw_stat aqr107_hw_stats[] = { ++ SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), ++ SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), ++}; ++#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) ++ ++struct aqr107_priv { ++ u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; ++}; ++ ++static int aqr107_get_sset_count(struct phy_device *phydev) ++{ ++ return AQR107_SGMII_STAT_SZ; ++} ++ ++static void aqr107_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) ++ strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, ++ ETH_GSTRING_LEN); ++} ++ ++static u64 aqr107_get_stat(struct phy_device *phydev, int index) ++{ ++ const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; ++ int len_l = min(stat->size, 16); ++ int len_h = stat->size - len_l; ++ u64 ret; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret = val & GENMASK(len_l - 1, 0); ++ if (len_h) { ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret += (val & GENMASK(len_h - 1, 0)) << 16; ++ } ++ ++ return ret; ++} ++ ++static void aqr107_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ struct aqr107_priv *priv = phydev->priv; ++ u64 val; ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { ++ val = aqr107_get_stat(phydev, i); ++ if (val == U64_MAX) ++ phydev_err(phydev, "Reading HW Statistics failed for %s\n", ++ aqr107_hw_stats[i].name); ++ else ++ priv->sgmii_stats[i] += val; ++ ++ data[i] = priv->sgmii_stats[i]; ++ } ++} ++ ++static int aqr_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ u16 reg; ++ int ret; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ return genphy_c45_pma_setup_forced(phydev); ++ ++ ret = genphy_c45_an_config_aneg(phydev); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ /* Clause 45 has no standardized support for 1000BaseT, therefore ++ * use vendor registers for this mode. ++ */ ++ reg = 0; ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; ++ ++ /* Handle the case when the 2.5G and 5G speeds are not advertised */ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_1000BASET_HALF | ++ MDIO_AN_VEND_PROV_1000BASET_FULL | ++ MDIO_AN_VEND_PROV_2500BASET_FULL | ++ MDIO_AN_VEND_PROV_5000BASET_FULL, reg); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ return genphy_c45_check_and_restart_aneg(phydev, changed); ++} ++ ++static int aqr_config_intr(struct phy_device *phydev) ++{ ++ bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; ++ int err; ++ ++ if (en) { ++ /* Clear any pending interrupts before enabling them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, ++ en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, ++ en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, ++ en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | ++ VEND1_GLOBAL_INT_VEND_MASK_AN : 0); ++ if (err < 0) ++ return err; ++ ++ if (!en) { ++ /* Clear any pending interrupts after we have disabled them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status; ++ ++ irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, ++ MDIO_AN_TX_VEND_INT_STATUS2); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int aqr_read_status(struct phy_device *phydev) ++{ ++ int val; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE) { ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ if (val < 0) ++ return val; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); ++ } ++ ++ return genphy_c45_read_status(phydev); ++} ++ ++static int aqr107_read_rate(struct phy_device *phydev) ++{ ++ u32 config_reg; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); ++ if (val < 0) ++ return val; ++ ++ if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { ++ case MDIO_AN_TX_VEND_STATUS1_10BASET: ++ phydev->speed = SPEED_10; ++ config_reg = VEND1_GLOBAL_CFG_10M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_100BASETX: ++ phydev->speed = SPEED_100; ++ config_reg = VEND1_GLOBAL_CFG_100M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_1000BASET: ++ phydev->speed = SPEED_1000; ++ config_reg = VEND1_GLOBAL_CFG_1G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_2500BASET: ++ phydev->speed = SPEED_2500; ++ config_reg = VEND1_GLOBAL_CFG_2_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_5000BASET: ++ phydev->speed = SPEED_5000; ++ config_reg = VEND1_GLOBAL_CFG_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_10GBASET: ++ phydev->speed = SPEED_10000; ++ config_reg = VEND1_GLOBAL_CFG_10G; ++ break; ++ default: ++ phydev->speed = SPEED_UNKNOWN; ++ return 0; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); ++ if (val < 0) ++ return val; ++ ++ if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == ++ VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) ++ phydev->rate_matching = RATE_MATCH_PAUSE; ++ else ++ phydev->rate_matching = RATE_MATCH_NONE; ++ ++ return 0; ++} ++ ++static int aqr107_read_status(struct phy_device *phydev) ++{ ++ int val, ret; ++ ++ ret = aqr_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) ++ return 0; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); ++ if (val < 0) ++ return val; ++ ++ switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: ++ phydev->interface = PHY_INTERFACE_MODE_10GKR; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: ++ phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: ++ phydev->interface = PHY_INTERFACE_MODE_10GBASER; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: ++ phydev->interface = PHY_INTERFACE_MODE_USXGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: ++ phydev->interface = PHY_INTERFACE_MODE_XAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: ++ phydev->interface = PHY_INTERFACE_MODE_RXAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ default: ++ phydev->interface = PHY_INTERFACE_MODE_NA; ++ break; ++ } ++ ++ /* Read possibly downshifted rate from vendor register */ ++ return aqr107_read_rate(phydev); ++} ++ ++static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) ++{ ++ int val, cnt, enable; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); ++ if (val < 0) ++ return val; ++ ++ enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); ++ cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++ ++ *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ int val = 0; ++ ++ if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) ++ return -E2BIG; ++ ++ if (cnt != DOWNSHIFT_DEV_DISABLE) { ++ val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; ++ val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); ++ } ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_DOWNSHIFT_EN | ++ MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++} ++ ++static int aqr107_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr107_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++/* If we configure settings whilst firmware is still initializing the chip, ++ * then these settings may be overwritten. Therefore make sure chip ++ * initialization has completed. Use presence of the firmware ID as ++ * indicator for initialization having completed. ++ * The chip also provides a "reset completed" bit, but it's cleared after ++ * read. Therefore function would time out if called again. ++ */ ++static int aqr107_wait_reset_complete(struct phy_device *phydev) ++{ ++ int val; ++ ++ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_FW_ID, val, val != 0, ++ 20000, 2000000, false); ++} ++ ++static void aqr107_chip_info(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor, build_id, prov_id; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); ++ fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); ++ if (val < 0) ++ return; ++ ++ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); ++ prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); ++ ++ phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", ++ fw_major, fw_minor, build_id, prov_id); ++} ++ ++static int aqr107_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX && ++ phydev->interface != PHY_INTERFACE_MODE_XGMII && ++ phydev->interface != PHY_INTERFACE_MODE_USXGMII && ++ phydev->interface != PHY_INTERFACE_MODE_10GKR && ++ phydev->interface != PHY_INTERFACE_MODE_10GBASER && ++ phydev->interface != PHY_INTERFACE_MODE_XAUI && ++ phydev->interface != PHY_INTERFACE_MODE_RXAUI) ++ return -ENODEV; ++ ++ WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, ++ "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static int aqcs109_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX) ++ return -ENODEV; ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ /* AQCS109 belongs to a chip family partially supporting 10G and 5G. ++ * PMA speed ability bits are the same for all members of the family, ++ * AQCS109 however supports speeds up to 2.5G only. ++ */ ++ ret = phy_set_max_speed(phydev, SPEED_2500); ++ if (ret) ++ return ret; ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static void aqr107_link_change_notify(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor; ++ bool downshift, short_reach, afr; ++ int mode, val; ++ ++ if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) ++ return; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ /* call failed or link partner is no Aquantia PHY */ ++ if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) ++ return; ++ ++ short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; ++ downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); ++ fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); ++ if (val < 0) ++ return; ++ ++ afr = val & MDIO_AN_RX_VEND_STAT3_AFR; ++ ++ phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", ++ fw_major, fw_minor, ++ short_reach ? ", short reach mode" : "", ++ downshift ? ", fast-retrain downshift advertised" : "", ++ afr ? ", fast reframe advertised" : ""); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); ++ if (val < 0) ++ return; ++ ++ mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); ++ if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) ++ phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); ++} ++ ++static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) ++{ ++ int val, err; ++ ++ /* The datasheet notes to wait at least 1ms after issuing a ++ * processor intensive operation before checking. ++ * We cannot use the 'sleep_before_read' parameter of read_poll_timeout ++ * because that just determines the maximum time slept, not the minimum. ++ */ ++ usleep_range(1000, 5000); ++ ++ err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_GEN_STAT2, val, ++ !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), ++ AQR107_OP_IN_PROG_SLEEP, ++ AQR107_OP_IN_PROG_TIMEOUT, false); ++ if (err) { ++ phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int aqr107_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ if (iface == PHY_INTERFACE_MODE_10GBASER || ++ iface == PHY_INTERFACE_MODE_2500BASEX || ++ iface == PHY_INTERFACE_MODE_NA) ++ return RATE_MATCH_PAUSE; ++ return RATE_MATCH_NONE; ++} ++ ++static int aqr107_suspend(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_resume(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_probe(struct phy_device *phydev) ++{ ++ phydev->priv = devm_kzalloc(&phydev->mdio.dev, ++ sizeof(struct aqr107_priv), GFP_KERNEL); ++ if (!phydev->priv) ++ return -ENOMEM; ++ ++ return aqr_hwmon_probe(phydev); ++} ++ ++static struct phy_driver aqr_driver[] = { ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), ++ .name = "Aquantia AQ1202", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), ++ .name = "Aquantia AQ2104", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR105), ++ .name = "Aquantia AQR105", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR106), ++ .name = "Aquantia AQR106", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR107), ++ .name = "Aquantia AQR107", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), ++ .name = "Aquantia AQCS109", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqcs109_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR405), ++ .name = "Aquantia AQR405", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), ++ .name = "Aquantia AQR113C", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++}; ++ ++module_phy_driver(aqr_driver); ++ ++static struct mdio_device_id __maybe_unused aqr_tbl[] = { ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, aqr_tbl); ++ ++MODULE_DESCRIPTION("Aquantia PHY driver"); ++MODULE_AUTHOR("Shaohui Xie "); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/net/phy/aquantia_hwmon.c ++++ /dev/null +@@ -1,250 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- +-#if IS_REACHABLE(CONFIG_HWMON) +- +-static umode_t aqr_hwmon_is_visible(const void *data, +- enum hwmon_sensor_types type, +- u32 attr, int channel) +-{ +- if (type != hwmon_temp) +- return 0; +- +- switch (attr) { +- case hwmon_temp_input: +- case hwmon_temp_min_alarm: +- case hwmon_temp_max_alarm: +- case hwmon_temp_lcrit_alarm: +- case hwmon_temp_crit_alarm: +- return 0444; +- case hwmon_temp_min: +- case hwmon_temp_max: +- case hwmon_temp_lcrit: +- case hwmon_temp_crit: +- return 0644; +- default: +- return 0; +- } +-} +- +-static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) +-{ +- int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (temp < 0) +- return temp; +- +- /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ +- *value = (s16)temp * 1000 / 256; +- +- return 0; +-} +- +-static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) +-{ +- int temp; +- +- if (value >= 128000 || value < -128000) +- return -ERANGE; +- +- temp = value * 256 / 1000; +- +- /* temp is in s16 range and we're interested in lower 16 bits only */ +- return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); +-} +- +-static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) +-{ +- int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (val < 0) +- return val; +- +- return !!(val & bit); +-} +- +-static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) +-{ +- int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); +- +- if (val < 0) +- return val; +- +- *value = val; +- +- return 0; +-} +- +-static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long *value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- int reg; +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_input: +- reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, +- VEND1_THERMAL_STAT2_VALID); +- if (reg < 0) +- return reg; +- if (!reg) +- return -EBUSY; +- +- return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); +- +- case hwmon_temp_lcrit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- case hwmon_temp_lcrit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_lcrit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static const struct hwmon_ops aqr_hwmon_ops = { +- .is_visible = aqr_hwmon_is_visible, +- .read = aqr_hwmon_read, +- .write = aqr_hwmon_write, +-}; +- +-static u32 aqr_hwmon_chip_config[] = { +- HWMON_C_REGISTER_TZ, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_chip = { +- .type = hwmon_chip, +- .config = aqr_hwmon_chip_config, +-}; +- +-static u32 aqr_hwmon_temp_config[] = { +- HWMON_T_INPUT | +- HWMON_T_MAX | HWMON_T_MIN | +- HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | +- HWMON_T_CRIT | HWMON_T_LCRIT | +- HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_temp = { +- .type = hwmon_temp, +- .config = aqr_hwmon_temp_config, +-}; +- +-static const struct hwmon_channel_info *aqr_hwmon_info[] = { +- &aqr_hwmon_chip, +- &aqr_hwmon_temp, +- NULL, +-}; +- +-static const struct hwmon_chip_info aqr_hwmon_chip_info = { +- .ops = &aqr_hwmon_ops, +- .info = aqr_hwmon_info, +-}; +- +-int aqr_hwmon_probe(struct phy_device *phydev) +-{ +- struct device *dev = &phydev->mdio.dev; +- struct device *hwmon_dev; +- char *hwmon_name; +- int i, j; +- +- hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); +- if (!hwmon_name) +- return -ENOMEM; +- +- for (i = j = 0; hwmon_name[i]; i++) { +- if (isalnum(hwmon_name[i])) { +- if (i != j) +- hwmon_name[j] = hwmon_name[i]; +- j++; +- } +- } +- hwmon_name[j] = '\0'; +- +- hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, +- phydev, &aqr_hwmon_chip_info, NULL); +- +- return PTR_ERR_OR_ZERO(hwmon_dev); +-} +- +-#endif +--- a/drivers/net/phy/aquantia_main.c ++++ /dev/null +@@ -1,844 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * Driver for Aquantia PHY +- * +- * Author: Shaohui Xie +- * +- * Copyright 2015 Freescale Semiconductor, Inc. +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-#define PHY_ID_AQ1202 0x03a1b445 +-#define PHY_ID_AQ2104 0x03a1b460 +-#define PHY_ID_AQR105 0x03a1b4a2 +-#define PHY_ID_AQR106 0x03a1b4d0 +-#define PHY_ID_AQR107 0x03a1b4e0 +-#define PHY_ID_AQCS109 0x03a1b5c2 +-#define PHY_ID_AQR405 0x03a1b4b0 +-#define PHY_ID_AQR113C 0x31c31c12 +- +-#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 +- +-#define MDIO_AN_VEND_PROV 0xc400 +-#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) +-#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) +-#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) +-#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 +- +-#define MDIO_AN_TX_VEND_STATUS1 0xc800 +-#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) +-#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 +-#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 +-#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 +-#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 +-#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 +-#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 +-#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 +-#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) +- +-#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 +-#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 +-#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) +- +-#define MDIO_AN_RX_LP_STAT1 0xe820 +-#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) +-#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) +-#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) +-#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) +-#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) +- +-#define MDIO_AN_RX_LP_STAT4 0xe823 +-#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) +-#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) +- +-#define MDIO_AN_RX_VEND_STAT3 0xe832 +-#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) +- +-/* MDIO_MMD_C22EXT */ +-#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 +-#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 +-#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 +-#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 +-#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 +-#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 +-#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 +-#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 +-#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a +-#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b +- +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- +-/* Sleep and timeout for checking if the Processor-Intensive +- * MDIO operation is finished +- */ +-#define AQR107_OP_IN_PROG_SLEEP 1000 +-#define AQR107_OP_IN_PROG_TIMEOUT 100000 +- +-struct aqr107_hw_stat { +- const char *name; +- int reg; +- int size; +-}; +- +-#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } +-static const struct aqr107_hw_stat aqr107_hw_stats[] = { +- SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), +- SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), +-}; +-#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) +- +-struct aqr107_priv { +- u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; +-}; +- +-static int aqr107_get_sset_count(struct phy_device *phydev) +-{ +- return AQR107_SGMII_STAT_SZ; +-} +- +-static void aqr107_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) +- strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, +- ETH_GSTRING_LEN); +-} +- +-static u64 aqr107_get_stat(struct phy_device *phydev, int index) +-{ +- const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; +- int len_l = min(stat->size, 16); +- int len_h = stat->size - len_l; +- u64 ret; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); +- if (val < 0) +- return U64_MAX; +- +- ret = val & GENMASK(len_l - 1, 0); +- if (len_h) { +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); +- if (val < 0) +- return U64_MAX; +- +- ret += (val & GENMASK(len_h - 1, 0)) << 16; +- } +- +- return ret; +-} +- +-static void aqr107_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- struct aqr107_priv *priv = phydev->priv; +- u64 val; +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { +- val = aqr107_get_stat(phydev, i); +- if (val == U64_MAX) +- phydev_err(phydev, "Reading HW Statistics failed for %s\n", +- aqr107_hw_stats[i].name); +- else +- priv->sgmii_stats[i] += val; +- +- data[i] = priv->sgmii_stats[i]; +- } +-} +- +-static int aqr_config_aneg(struct phy_device *phydev) +-{ +- bool changed = false; +- u16 reg; +- int ret; +- +- if (phydev->autoneg == AUTONEG_DISABLE) +- return genphy_c45_pma_setup_forced(phydev); +- +- ret = genphy_c45_an_config_aneg(phydev); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- /* Clause 45 has no standardized support for 1000BaseT, therefore +- * use vendor registers for this mode. +- */ +- reg = 0; +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; +- +- /* Handle the case when the 2.5G and 5G speeds are not advertised */ +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_1000BASET_HALF | +- MDIO_AN_VEND_PROV_1000BASET_FULL | +- MDIO_AN_VEND_PROV_2500BASET_FULL | +- MDIO_AN_VEND_PROV_5000BASET_FULL, reg); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- return genphy_c45_check_and_restart_aneg(phydev, changed); +-} +- +-static int aqr_config_intr(struct phy_device *phydev) +-{ +- bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; +- int err; +- +- if (en) { +- /* Clear any pending interrupts before enabling them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, +- en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, +- en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, +- en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | +- VEND1_GLOBAL_INT_VEND_MASK_AN : 0); +- if (err < 0) +- return err; +- +- if (!en) { +- /* Clear any pending interrupts after we have disabled them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- return 0; +-} +- +-static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status; +- +- irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, +- MDIO_AN_TX_VEND_INT_STATUS2); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static int aqr_read_status(struct phy_device *phydev) +-{ +- int val; +- +- if (phydev->autoneg == AUTONEG_ENABLE) { +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- if (val < 0) +- return val; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); +- } +- +- return genphy_c45_read_status(phydev); +-} +- +-static int aqr107_read_rate(struct phy_device *phydev) +-{ +- u32 config_reg; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); +- if (val < 0) +- return val; +- +- if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { +- case MDIO_AN_TX_VEND_STATUS1_10BASET: +- phydev->speed = SPEED_10; +- config_reg = VEND1_GLOBAL_CFG_10M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_100BASETX: +- phydev->speed = SPEED_100; +- config_reg = VEND1_GLOBAL_CFG_100M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_1000BASET: +- phydev->speed = SPEED_1000; +- config_reg = VEND1_GLOBAL_CFG_1G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_2500BASET: +- phydev->speed = SPEED_2500; +- config_reg = VEND1_GLOBAL_CFG_2_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_5000BASET: +- phydev->speed = SPEED_5000; +- config_reg = VEND1_GLOBAL_CFG_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_10GBASET: +- phydev->speed = SPEED_10000; +- config_reg = VEND1_GLOBAL_CFG_10G; +- break; +- default: +- phydev->speed = SPEED_UNKNOWN; +- return 0; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); +- if (val < 0) +- return val; +- +- if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == +- VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) +- phydev->rate_matching = RATE_MATCH_PAUSE; +- else +- phydev->rate_matching = RATE_MATCH_NONE; +- +- return 0; +-} +- +-static int aqr107_read_status(struct phy_device *phydev) +-{ +- int val, ret; +- +- ret = aqr_read_status(phydev); +- if (ret) +- return ret; +- +- if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) +- return 0; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); +- if (val < 0) +- return val; +- +- switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: +- phydev->interface = PHY_INTERFACE_MODE_10GKR; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: +- phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: +- phydev->interface = PHY_INTERFACE_MODE_10GBASER; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: +- phydev->interface = PHY_INTERFACE_MODE_USXGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: +- phydev->interface = PHY_INTERFACE_MODE_XAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: +- phydev->interface = PHY_INTERFACE_MODE_RXAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- break; +- default: +- phydev->interface = PHY_INTERFACE_MODE_NA; +- break; +- } +- +- /* Read possibly downshifted rate from vendor register */ +- return aqr107_read_rate(phydev); +-} +- +-static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) +-{ +- int val, cnt, enable; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); +- if (val < 0) +- return val; +- +- enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); +- cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +- +- *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- int val = 0; +- +- if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) +- return -E2BIG; +- +- if (cnt != DOWNSHIFT_DEV_DISABLE) { +- val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; +- val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); +- } +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_DOWNSHIFT_EN | +- MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +-} +- +-static int aqr107_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr107_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-/* If we configure settings whilst firmware is still initializing the chip, +- * then these settings may be overwritten. Therefore make sure chip +- * initialization has completed. Use presence of the firmware ID as +- * indicator for initialization having completed. +- * The chip also provides a "reset completed" bit, but it's cleared after +- * read. Therefore function would time out if called again. +- */ +-static int aqr107_wait_reset_complete(struct phy_device *phydev) +-{ +- int val; +- +- return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_FW_ID, val, val != 0, +- 20000, 2000000, false); +-} +- +-static void aqr107_chip_info(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor, build_id, prov_id; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); +- fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); +- if (val < 0) +- return; +- +- build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); +- prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); +- +- phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", +- fw_major, fw_minor, build_id, prov_id); +-} +- +-static int aqr107_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX && +- phydev->interface != PHY_INTERFACE_MODE_XGMII && +- phydev->interface != PHY_INTERFACE_MODE_USXGMII && +- phydev->interface != PHY_INTERFACE_MODE_10GKR && +- phydev->interface != PHY_INTERFACE_MODE_10GBASER && +- phydev->interface != PHY_INTERFACE_MODE_XAUI && +- phydev->interface != PHY_INTERFACE_MODE_RXAUI) +- return -ENODEV; +- +- WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, +- "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static int aqcs109_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX) +- return -ENODEV; +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- /* AQCS109 belongs to a chip family partially supporting 10G and 5G. +- * PMA speed ability bits are the same for all members of the family, +- * AQCS109 however supports speeds up to 2.5G only. +- */ +- ret = phy_set_max_speed(phydev, SPEED_2500); +- if (ret) +- return ret; +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static void aqr107_link_change_notify(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor; +- bool downshift, short_reach, afr; +- int mode, val; +- +- if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) +- return; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- /* call failed or link partner is no Aquantia PHY */ +- if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) +- return; +- +- short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; +- downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); +- fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); +- if (val < 0) +- return; +- +- afr = val & MDIO_AN_RX_VEND_STAT3_AFR; +- +- phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", +- fw_major, fw_minor, +- short_reach ? ", short reach mode" : "", +- downshift ? ", fast-retrain downshift advertised" : "", +- afr ? ", fast reframe advertised" : ""); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); +- if (val < 0) +- return; +- +- mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); +- if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) +- phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); +-} +- +-static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) +-{ +- int val, err; +- +- /* The datasheet notes to wait at least 1ms after issuing a +- * processor intensive operation before checking. +- * We cannot use the 'sleep_before_read' parameter of read_poll_timeout +- * because that just determines the maximum time slept, not the minimum. +- */ +- usleep_range(1000, 5000); +- +- err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_GEN_STAT2, val, +- !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), +- AQR107_OP_IN_PROG_SLEEP, +- AQR107_OP_IN_PROG_TIMEOUT, false); +- if (err) { +- phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); +- return err; +- } +- +- return 0; +-} +- +-static int aqr107_get_rate_matching(struct phy_device *phydev, +- phy_interface_t iface) +-{ +- if (iface == PHY_INTERFACE_MODE_10GBASER || +- iface == PHY_INTERFACE_MODE_2500BASEX || +- iface == PHY_INTERFACE_MODE_NA) +- return RATE_MATCH_PAUSE; +- return RATE_MATCH_NONE; +-} +- +-static int aqr107_suspend(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_resume(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_probe(struct phy_device *phydev) +-{ +- phydev->priv = devm_kzalloc(&phydev->mdio.dev, +- sizeof(struct aqr107_priv), GFP_KERNEL); +- if (!phydev->priv) +- return -ENOMEM; +- +- return aqr_hwmon_probe(phydev); +-} +- +-static struct phy_driver aqr_driver[] = { +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), +- .name = "Aquantia AQ1202", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), +- .name = "Aquantia AQ2104", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR105), +- .name = "Aquantia AQR105", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR106), +- .name = "Aquantia AQR106", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR107), +- .name = "Aquantia AQR107", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), +- .name = "Aquantia AQCS109", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqcs109_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR405), +- .name = "Aquantia AQR405", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), +- .name = "Aquantia AQR113C", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-}; +- +-module_phy_driver(aqr_driver); +- +-static struct mdio_device_id __maybe_unused aqr_tbl[] = { +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(mdio, aqr_tbl); +- +-MODULE_DESCRIPTION("Aquantia PHY driver"); +-MODULE_AUTHOR("Shaohui Xie "); +-MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-5.15/737-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch b/target/linux/generic/backport-5.15/737-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch new file mode 100644 index 0000000000..2b94522723 --- /dev/null +++ b/target/linux/generic/backport-5.15/737-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch @@ -0,0 +1,183 @@ +From e1fbfa4a995d42e02e22b0dff2f8b4fdee1504b3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:42 +0100 +Subject: [PATCH 2/3] net: phy: aquantia: move MMD_VEND define to header + +Move MMD_VEND define to header to clean things up and in preparation for +firmware loading support that require some define placed in +aquantia_main. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia.h | 69 +++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_hwmon.c | 14 ----- + drivers/net/phy/aquantia/aquantia_main.c | 55 ------------------ + 3 files changed, 69 insertions(+), 69 deletions(-) + +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -9,6 +9,75 @@ + #include + #include + ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ + #if IS_REACHABLE(CONFIG_HWMON) + int aqr_hwmon_probe(struct phy_device *phydev); + #else +--- a/drivers/net/phy/aquantia/aquantia_hwmon.c ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -13,20 +13,6 @@ + + #include "aquantia.h" + +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- + #if IS_REACHABLE(CONFIG_HWMON) + + static umode_t aqr_hwmon_is_visible(const void *data, +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -89,61 +89,6 @@ + #define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a + #define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b + +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- + /* Sleep and timeout for checking if the Processor-Intensive + * MDIO operation is finished + */ diff --git a/target/linux/generic/backport-5.15/737-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch b/target/linux/generic/backport-5.15/737-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch new file mode 100644 index 0000000000..1ae5966df6 --- /dev/null +++ b/target/linux/generic/backport-5.15/737-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch @@ -0,0 +1,504 @@ +From e93984ebc1c82bd34f7a1b3391efaceee0a8ae96 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 14 Nov 2023 15:08:43 +0100 +Subject: [PATCH 3/3] net: phy: aquantia: add firmware load support + +Aquantia PHY-s require firmware to be loaded before they start operating. +It can be automatically loaded in case when there is a SPI-NOR connected +to Aquantia PHY-s or can be loaded from the host via MDIO. + +This patch adds support for loading the firmware via MDIO as in most cases +there is no SPI-NOR being used to save on cost. +Firmware loading code itself is ported from mainline U-boot with cleanups. + +The firmware has mixed values both in big and little endian. +PHY core itself is big-endian but it expects values to be in little-endian. +The firmware is little-endian but CRC-16 value for it is stored at the end +of firmware in big-endian. + +It seems the PHY does the conversion internally from firmware that is +little-endian to the PHY that is big-endian on using the mailbox +but mailbox returns a big-endian CRC-16 to verify the written data +integrity. + +Co-developed-by: Christian Marangi +Signed-off-by: Robert Marko +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/Kconfig | 1 + + drivers/net/phy/aquantia/Makefile | 2 +- + drivers/net/phy/aquantia/aquantia.h | 32 ++ + drivers/net/phy/aquantia/aquantia_firmware.c | 370 +++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 6 + + 5 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/phy/aquantia/aquantia_firmware.c + +--- a/drivers/net/phy/aquantia/Kconfig ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config AQUANTIA_PHY + tristate "Aquantia PHYs" ++ select CRC_CCITT + help + Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- a/drivers/net/phy/aquantia/Makefile ++++ b/drivers/net/phy/aquantia/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-aquantia-objs += aquantia_main.o ++aquantia-objs += aquantia_main.o aquantia_firmware.o + ifdef CONFIG_HWMON + aquantia-objs += aquantia_hwmon.o + endif +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -10,10 +10,35 @@ + #include + + /* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_SC 0x0 ++#define VEND1_GLOBAL_SC_SOFT_RESET BIT(15) ++#define VEND1_GLOBAL_SC_LOW_POWER BIT(11) ++ + #define VEND1_GLOBAL_FW_ID 0x0020 + #define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) + #define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) + ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1 0x0200 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE BIT(15) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE BIT(14) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET BIT(12) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_BUSY BIT(8) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE2 0x0201 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3 0x0202 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4 0x0203 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK GENMASK(15, 2) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK, (u16)(x)) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5 0x0204 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6 0x0205 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK, (u16)(x)) ++ + /* The following registers all have similar layouts; first the registers... */ + #define VEND1_GLOBAL_CFG_10M 0x0310 + #define VEND1_GLOBAL_CFG_100M 0x031b +@@ -28,6 +53,11 @@ + #define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 + + /* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_GLOBAL_CONTROL2 0xc001 ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST BIT(15) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD BIT(6) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL BIT(0) ++ + #define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 + #define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 + #define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +@@ -83,3 +113,5 @@ int aqr_hwmon_probe(struct phy_device *p + #else + static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } + #endif ++ ++int aqr_firmware_load(struct phy_device *phydev); +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_firmware.c +@@ -0,0 +1,370 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "aquantia.h" ++ ++#define UP_RESET_SLEEP 100 ++ ++/* addresses of memory segments in the phy */ ++#define DRAM_BASE_ADDR 0x3FFE0000 ++#define IRAM_BASE_ADDR 0x40000000 ++ ++/* firmware image format constants */ ++#define VERSION_STRING_SIZE 0x40 ++#define VERSION_STRING_OFFSET 0x0200 ++/* primary offset is written at an offset from the start of the fw blob */ ++#define PRIMARY_OFFSET_OFFSET 0x8 ++/* primary offset needs to be then added to a base offset */ ++#define PRIMARY_OFFSET_SHIFT 12 ++#define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT) ++#define HEADER_OFFSET 0x300 ++ ++struct aqr_fw_header { ++ u32 padding; ++ u8 iram_offset[3]; ++ u8 iram_size[3]; ++ u8 dram_offset[3]; ++ u8 dram_size[3]; ++} __packed; ++ ++enum aqr_fw_src { ++ AQR_FW_SRC_NVMEM = 0, ++ AQR_FW_SRC_FS, ++}; ++ ++static const char * const aqr_fw_src_string[] = { ++ [AQR_FW_SRC_NVMEM] = "NVMEM", ++ [AQR_FW_SRC_FS] = "FS", ++}; ++ ++/* AQR firmware doesn't have fixed offsets for iram and dram section ++ * but instead provide an header with the offset to use on reading ++ * and parsing the firmware. ++ * ++ * AQR firmware can't be trusted and each offset is validated to be ++ * not negative and be in the size of the firmware itself. ++ */ ++static bool aqr_fw_validate_get(size_t size, size_t offset, size_t get_size) ++{ ++ return offset + get_size <= size; ++} ++ ++static int aqr_fw_get_be16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_be16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_le16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le24(const u8 *data, size_t offset, size_t size, u32 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u8) * 3)) ++ return -EINVAL; ++ ++ *value = get_unaligned_le24(data + offset); ++ ++ return 0; ++} ++ ++/* load data into the phy's memory */ ++static int aqr_fw_load_memory(struct phy_device *phydev, u32 addr, ++ const u8 *data, size_t len) ++{ ++ u16 crc = 0, up_crc; ++ size_t pos; ++ ++ /* PHY expect addr in LE */ ++ addr = (__force u32)cpu_to_le32(addr); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr)); ++ ++ /* We assume and enforce the size to be word aligned. ++ * If a firmware that is not word aligned is found, please report upstream. ++ */ ++ for (pos = 0; pos < len; pos += sizeof(u32)) { ++ u32 word; ++ ++ /* FW data is always stored in little-endian */ ++ word = get_unaligned((const u32 *)(data + pos)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5, ++ VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE6, ++ VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE | ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE); ++ ++ /* calculate CRC as we load data to the mailbox. ++ * We convert word to big-endian as PHY is BE and mailbox will ++ * return a BE CRC. ++ */ ++ word = (__force u32)cpu_to_be32(word); ++ crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word)); ++ } ++ ++ up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2); ++ if (crc != up_crc) { ++ phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n", ++ crc, up_crc); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int aqr_fw_boot(struct phy_device *phydev, const u8 *data, size_t size, ++ enum aqr_fw_src fw_src) ++{ ++ u16 calculated_crc, read_crc, read_primary_offset; ++ u32 iram_offset = 0, iram_size = 0; ++ u32 dram_offset = 0, dram_size = 0; ++ char version[VERSION_STRING_SIZE]; ++ u32 primary_offset = 0; ++ int ret; ++ ++ /* extract saved CRC at the end of the fw ++ * CRC is saved in big-endian as PHY is BE ++ */ ++ ret = aqr_fw_get_be16(data, size - sizeof(u16), size, &read_crc); ++ if (ret) { ++ phydev_err(phydev, "bad firmware CRC in firmware\n"); ++ return ret; ++ } ++ calculated_crc = crc_ccitt_false(0, data, size - sizeof(u16)); ++ if (read_crc != calculated_crc) { ++ phydev_err(phydev, "bad firmware CRC: file 0x%04x calculated 0x%04x\n", ++ read_crc, calculated_crc); ++ return -EINVAL; ++ } ++ ++ /* Get the primary offset to extract DRAM and IRAM sections. */ ++ ret = aqr_fw_get_le16(data, PRIMARY_OFFSET_OFFSET, size, &read_primary_offset); ++ if (ret) { ++ phydev_err(phydev, "bad primary offset in firmware\n"); ++ return ret; ++ } ++ primary_offset = PRIMARY_OFFSET(read_primary_offset); ++ ++ /* Find the DRAM and IRAM sections within the firmware file. ++ * Make sure the fw_header is correctly in the firmware. ++ */ ++ if (!aqr_fw_validate_get(size, primary_offset + HEADER_OFFSET, ++ sizeof(struct aqr_fw_header))) { ++ phydev_err(phydev, "bad fw_header in firmware\n"); ++ return -EINVAL; ++ } ++ ++ /* offset are in LE and values needs to be converted to cpu endian */ ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_offset), ++ size, &iram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad iram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_size), ++ size, &iram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid iram size in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_offset), ++ size, &dram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad dram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_size), ++ size, &dram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid dram size in firmware\n"); ++ return ret; ++ } ++ ++ /* Increment the offset with the primary offset. ++ * Validate iram/dram offset and size. ++ */ ++ iram_offset += primary_offset; ++ if (iram_size % sizeof(u32)) { ++ phydev_err(phydev, "iram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, iram_offset, iram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ dram_offset += primary_offset; ++ if (dram_size % sizeof(u32)) { ++ phydev_err(phydev, "dram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, dram_offset, dram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ phydev_dbg(phydev, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n", ++ primary_offset, iram_offset, iram_size, dram_offset, dram_size); ++ ++ if (!aqr_fw_validate_get(size, dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE)) { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ strscpy(version, (char *)data + dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE); ++ if (version[0] == '\0') { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ phydev_info(phydev, "loading firmware version '%s' from '%s'\n", version, ++ aqr_fw_src_string[fw_src]); ++ ++ /* stall the microcprocessor */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ phydev_dbg(phydev, "loading DRAM 0x%08x from offset=%d size=%d\n", ++ DRAM_BASE_ADDR, dram_offset, dram_size); ++ ret = aqr_fw_load_memory(phydev, DRAM_BASE_ADDR, data + dram_offset, ++ dram_size); ++ if (ret) ++ return ret; ++ ++ phydev_dbg(phydev, "loading IRAM 0x%08x from offset=%d size=%d\n", ++ IRAM_BASE_ADDR, iram_offset, iram_size); ++ ret = aqr_fw_load_memory(phydev, IRAM_BASE_ADDR, data + iram_offset, ++ iram_size); ++ if (ret) ++ return ret; ++ ++ /* make sure soft reset and low power mode are clear */ ++ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_SC, ++ VEND1_GLOBAL_SC_SOFT_RESET | VEND1_GLOBAL_SC_LOW_POWER); ++ ++ /* Release the microprocessor. UP_RESET must be held for 100 usec. */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST); ++ usleep_range(UP_RESET_SLEEP, UP_RESET_SLEEP * 2); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ return 0; ++} ++ ++static int aqr_firmware_load_nvmem(struct phy_device *phydev) ++{ ++ struct nvmem_cell *cell; ++ size_t size; ++ u8 *buf; ++ int ret; ++ ++ cell = nvmem_cell_get(&phydev->mdio.dev, "firmware"); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ buf = nvmem_cell_read(cell, &size); ++ if (IS_ERR(buf)) { ++ ret = PTR_ERR(buf); ++ goto exit; ++ } ++ ++ ret = aqr_fw_boot(phydev, buf, size, AQR_FW_SRC_NVMEM); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ kfree(buf); ++exit: ++ nvmem_cell_put(cell); ++ ++ return ret; ++} ++ ++static int aqr_firmware_load_fs(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ const struct firmware *fw; ++ const char *fw_name; ++ int ret; ++ ++ ret = of_property_read_string(dev->of_node, "firmware-name", ++ &fw_name); ++ if (ret) ++ return ret; ++ ++ ret = request_firmware(&fw, fw_name, dev); ++ if (ret) { ++ phydev_err(phydev, "failed to find FW file %s (%d)\n", ++ fw_name, ret); ++ return ret; ++ } ++ ++ ret = aqr_fw_boot(phydev, fw->data, fw->size, AQR_FW_SRC_FS); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ release_firmware(fw); ++ ++ return ret; ++} ++ ++int aqr_firmware_load(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check if the firmware is not already loaded by pooling ++ * the current version returned by the PHY. If 0 is returned, ++ * no firmware is loaded. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (ret > 0) ++ goto exit; ++ ++ ret = aqr_firmware_load_nvmem(phydev); ++ if (!ret) ++ goto exit; ++ ++ ret = aqr_firmware_load_fs(phydev); ++ if (ret) ++ return ret; ++ ++exit: ++ return 0; ++} +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -658,11 +658,17 @@ static int aqr107_resume(struct phy_devi + + static int aqr107_probe(struct phy_device *phydev) + { ++ int ret; ++ + phydev->priv = devm_kzalloc(&phydev->mdio.dev, + sizeof(struct aqr107_priv), GFP_KERNEL); + if (!phydev->priv) + return -ENOMEM; + ++ ret = aqr_firmware_load(phydev); ++ if (ret) ++ return ret; ++ + return aqr_hwmon_probe(phydev); + } + diff --git a/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch index 7eb097f86d..7c0a490695 100644 --- a/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ b/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch @@ -31,7 +31,7 @@ Signed-off-by: David S. Miller F: drivers/net/phy/motorcomm.c --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -245,7 +245,7 @@ config MOTORCOMM_PHY +@@ -242,7 +242,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch b/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch index da60c63905..94d09092cf 100644 --- a/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch +++ b/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch @@ -22,7 +22,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -245,7 +245,7 @@ config MOTORCOMM_PHY +@@ -242,7 +242,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch b/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch index 9dce5a8add..a8b9e3d13b 100644 --- a/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch +++ b/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch @@ -19,7 +19,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -245,7 +245,7 @@ config MOTORCOMM_PHY +@@ -242,7 +242,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/target/linux/generic/backport-5.15/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch b/target/linux/generic/backport-5.15/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch new file mode 100644 index 0000000000..010ca9b68a --- /dev/null +++ b/target/linux/generic/backport-5.15/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch @@ -0,0 +1,170 @@ +From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Thu, 20 Jul 2023 19:15:09 +0800 +Subject: [PATCH] net: phy: motorcomm: Add pad drive strength cfg support + +The motorcomm phy (YT8531) supports the ability to adjust the drive +strength of the rx_clk/rx_data, and the default strength may not be +suitable for all boards. So add configurable options to better match +the boards.(e.g. StarFive VisionFive 2) + +When we configure the drive strength, we need to read the current +LDO voltage value to ensure that it is a legal value at that LDO +voltage. + +Reviewed-by: Hal Feng +Signed-off-by: Samin Guo +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 118 insertions(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -163,6 +163,10 @@ + + #define YT8521_CHIP_CONFIG_REG 0xA001 + #define YT8521_CCR_SW_RST BIT(15) ++#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) ++#define YT8531_LDO_VOL_3V3 0x0 ++#define YT8531_LDO_VOL_1V8 0x2 ++ + /* 1b0 disable 1.9ns rxc clock delay *default* + * 1b1 enable 1.9ns rxc clock delay + */ +@@ -236,6 +240,12 @@ + */ + #define YTPHY_WCR_TYPE_PULSE BIT(0) + ++#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 ++#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) ++#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ ++#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ ++#define YT8531_RGMII_RX_DS_DEFAULT 0x3 ++ + #define YTPHY_SYNCE_CFG_REG 0xA012 + #define YT8521_SCR_SYNCE_ENABLE BIT(5) + /* 1b0 output 25m clock +@@ -835,6 +845,110 @@ static int ytphy_rgmii_clk_delay_config_ + } + + /** ++ * struct ytphy_ldo_vol_map - map a current value to a register value ++ * @vol: ldo voltage ++ * @ds: value in the register ++ * @cur: value in device configuration ++ */ ++struct ytphy_ldo_vol_map { ++ u32 vol; ++ u32 ds; ++ u32 cur; ++}; ++ ++static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, ++}; ++ ++static u32 yt8531_get_ldo_vol(struct phy_device *phydev) ++{ ++ u32 val; ++ ++ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); ++ val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); ++ ++ return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; ++} ++ ++static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) ++{ ++ u32 vol; ++ int i; ++ ++ vol = yt8531_get_ldo_vol(phydev); ++ for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { ++ if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) ++ return yt8531_ldo_vol[i].ds; ++ } ++ ++ return -EINVAL; ++} ++ ++static int yt8531_set_ds(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ u32 ds_field_low, ds_field_hi, val; ++ int ret, ds; ++ ++ /* set rgmii rx clk driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXC_DS_MASK, ++ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); ++ if (ret < 0) ++ return ret; ++ ++ /* set rgmii rx data driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ds_field_hi = FIELD_GET(BIT(2), ds); ++ ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); ++ ++ ds_field_low = FIELD_GET(GENMASK(1, 0), ds); ++ ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, ++ ds_field_low | ds_field_hi); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/** + * yt8521_probe() - read chip config then set suitable polling_mode + * @phydev: a pointer to a &struct phy_device + * +@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy + return ret; + } + ++ ret = yt8531_set_ds(phydev); ++ if (ret < 0) ++ return ret; ++ + return 0; + } + diff --git a/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch b/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch index cda77e3e2d..a0cb367ba7 100644 --- a/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch +++ b/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -756,6 +756,18 @@ static void phylink_resolve_flow(struct +@@ -759,6 +759,18 @@ static void phylink_resolve_flow(struct } } @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski static void phylink_mac_config(struct phylink *pl, const struct phylink_link_state *state) { -@@ -787,6 +799,7 @@ static void phylink_major_config(struct +@@ -790,6 +802,7 @@ static void phylink_major_config(struct const struct phylink_link_state *state) { struct phylink_pcs *pcs = NULL; @@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski int err; phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); -@@ -799,8 +812,12 @@ static void phylink_major_config(struct +@@ -802,8 +815,12 @@ static void phylink_major_config(struct pcs); return; } @@ -57,7 +57,7 @@ Signed-off-by: Jakub Kicinski if (pl->mac_ops->mac_prepare) { err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode, state->interface); -@@ -814,8 +831,10 @@ static void phylink_major_config(struct +@@ -817,8 +834,10 @@ static void phylink_major_config(struct /* If we have a new PCS, switch to the new PCS after preparing the MAC * for the change. */ @@ -70,7 +70,7 @@ Signed-off-by: Jakub Kicinski phylink_mac_config(pl, state); -@@ -841,6 +860,8 @@ static void phylink_major_config(struct +@@ -844,6 +863,8 @@ static void phylink_major_config(struct phylink_err(pl, "mac_finish failed: %pe\n", ERR_PTR(err)); } diff --git a/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch b/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch index f1f359bad7..fec2fddfda 100644 --- a/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch +++ b/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch @@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -764,7 +764,7 @@ static void phylink_pcs_poll_stop(struct +@@ -767,7 +767,7 @@ static void phylink_pcs_poll_stop(struct static void phylink_pcs_poll_start(struct phylink *pl) { diff --git a/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch index c8176c90f5..71b09cbe75 100644 --- a/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch +++ b/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller bool mac_link_dropped; bool using_mac_select_pcs; -@@ -795,6 +800,22 @@ static void phylink_mac_pcs_an_restart(s +@@ -798,6 +803,22 @@ static void phylink_mac_pcs_an_restart(s } } @@ -58,7 +58,7 @@ Signed-off-by: David S. Miller static void phylink_major_config(struct phylink *pl, bool restart, const struct phylink_link_state *state) { -@@ -832,12 +853,16 @@ static void phylink_major_config(struct +@@ -835,12 +856,16 @@ static void phylink_major_config(struct * for the change. */ if (pcs_changed) { @@ -75,7 +75,7 @@ Signed-off-by: David S. Miller if (pl->pcs_ops) { err = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode, state->interface, -@@ -1261,6 +1286,7 @@ struct phylink *phylink_create(struct ph +@@ -1264,6 +1289,7 @@ struct phylink *phylink_create(struct ph pl->link_config.speed = SPEED_UNKNOWN; pl->link_config.duplex = DUPLEX_UNKNOWN; pl->link_config.an_enabled = true; @@ -83,7 +83,7 @@ Signed-off-by: David S. Miller pl->mac_ops = mac_ops; __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -1652,6 +1678,8 @@ void phylink_start(struct phylink *pl) +@@ -1655,6 +1681,8 @@ void phylink_start(struct phylink *pl) if (pl->netdev) netif_carrier_off(pl->netdev); @@ -92,7 +92,7 @@ Signed-off-by: David S. Miller /* Apply the link configuration to the MAC when starting. This allows * a fixed-link to start with the correct parameters, and also * ensures that we set the appropriate advertisement for Serdes links. -@@ -1662,6 +1690,8 @@ void phylink_start(struct phylink *pl) +@@ -1665,6 +1693,8 @@ void phylink_start(struct phylink *pl) */ phylink_mac_initial_config(pl, true); @@ -101,7 +101,7 @@ Signed-off-by: David S. Miller clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); phylink_run_resolve(pl); -@@ -1681,16 +1711,9 @@ void phylink_start(struct phylink *pl) +@@ -1684,16 +1714,9 @@ void phylink_start(struct phylink *pl) poll = true; } @@ -120,7 +120,7 @@ Signed-off-by: David S. Miller if (poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) -@@ -1727,6 +1750,10 @@ void phylink_stop(struct phylink *pl) +@@ -1730,6 +1753,10 @@ void phylink_stop(struct phylink *pl) } phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); diff --git a/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch b/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch index a2168aaba5..698e524c35 100644 --- a/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch +++ b/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch @@ -18,7 +18,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c -@@ -1377,11 +1377,12 @@ static int ax88179_bind(struct usbnet *d +@@ -1333,11 +1333,12 @@ static int ax88179_bind(struct usbnet *d dev->mii.phy_id = 0x03; dev->mii.supports_gmii = 1; @@ -33,9 +33,9 @@ Signed-off-by: David S. Miller + + netif_set_gso_max_size(dev->net, 16384); - /* Enable checksum offload */ - *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | -@@ -1587,17 +1588,19 @@ ax88179_tx_fixup(struct usbnet *dev, str + ax88179_reset(dev); + +@@ -1507,17 +1508,19 @@ ax88179_tx_fixup(struct usbnet *dev, str { u32 tx_hdr1, tx_hdr2; int frame_size = dev->maxpacket; @@ -57,7 +57,7 @@ Signed-off-by: David S. Miller if ((skb_header_cloned(skb) || headroom < 0) && pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) { dev_kfree_skb_any(skb); -@@ -1608,6 +1611,8 @@ ax88179_tx_fixup(struct usbnet *dev, str +@@ -1528,6 +1531,8 @@ ax88179_tx_fixup(struct usbnet *dev, str put_unaligned_le32(tx_hdr1, ptr); put_unaligned_le32(tx_hdr2, ptr + 4); diff --git a/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch index 3e60f91a2a..6e5ac8b249 100644 --- a/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch +++ b/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch @@ -153,7 +153,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -582,6 +583,7 @@ struct macsec_ops; +@@ -590,6 +591,7 @@ struct macsec_ops; * @phy_num_led_triggers: Number of triggers in @phy_led_triggers * @led_link_trigger: LED trigger for link up/down * @last_triggered: last LED trigger for link speed @@ -161,7 +161,7 @@ Signed-off-by: David S. Miller * @master_slave_set: User requested master/slave configuration * @master_slave_get: Current master/slave advertisement * @master_slave_state: Current master/slave configuration -@@ -668,6 +670,7 @@ struct phy_device { +@@ -678,6 +680,7 @@ struct phy_device { struct phy_led_trigger *led_link_trigger; #endif @@ -169,7 +169,7 @@ Signed-off-by: David S. Miller /* * Interrupt number for this PHY -@@ -739,6 +742,19 @@ struct phy_tdr_config { +@@ -749,6 +752,19 @@ struct phy_tdr_config { #define PHY_PAIR_ALL -1 /** diff --git a/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index f990557cc7..3968a884b8 100644 --- a/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -59,7 +59,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -745,15 +745,19 @@ struct phy_tdr_config { +@@ -755,15 +755,19 @@ struct phy_tdr_config { * struct phy_led: An LED driven by the PHY * * @list: List of LEDs @@ -79,7 +79,7 @@ Signed-off-by: David S. Miller /** * struct phy_driver - Driver structure for a particular PHY type * -@@ -953,6 +957,15 @@ struct phy_driver { +@@ -978,6 +982,15 @@ struct phy_driver { int (*get_sqi)(struct phy_device *dev); /** @get_sqi_max: Get the maximum signal quality indication */ int (*get_sqi_max)(struct phy_device *dev); diff --git a/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 4814688de4..35e1a1c723 100644 --- a/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -52,7 +52,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -966,6 +966,18 @@ struct phy_driver { +@@ -991,6 +991,18 @@ struct phy_driver { */ int (*led_brightness_set)(struct phy_device *dev, u8 index, enum led_brightness value); diff --git a/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch b/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch index 6c20521701..855d45311e 100644 --- a/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch +++ b/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch @@ -148,7 +148,7 @@ Signed-off-by: Greg Kroah-Hartman * of_find_node_by_phandle - Find a node given a phandle --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -2128,8 +2128,8 @@ of_register_spi_device(struct spi_contro +@@ -2140,8 +2140,8 @@ of_register_spi_device(struct spi_contro } /* Select device driver */ diff --git a/target/linux/generic/backport-5.15/834-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch b/target/linux/generic/backport-5.15/834-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch new file mode 100644 index 0000000000..1bf3ba35b6 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch @@ -0,0 +1,94 @@ +From 401df0d4f4098ecc9c5278da2f50756d62e5b37d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:03 +0100 +Subject: [PATCH] nvmem: layouts: refactor .add_cells() callback arguments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simply pass whole "struct nvmem_layout" instead of single variables. +There is nothing in "struct nvmem_layout" that we have to hide from +layout drivers. They also access it during .probe() and .remove(). + +Thanks to this change: + +1. API gets more consistent + All layouts drivers callbacks get the same argument + +2. Layouts get correct device + Before this change NVMEM core code was passing NVMEM device instead + of layout device. That resulted in: + * Confusing prints + * Calling devm_*() helpers on wrong device + * Helpers like of_device_get_match_data() dereferencing NULLs + +3. It gets possible to get match data + First of all nvmem_layout_get_match_data() requires passing "struct + nvmem_layout" which .add_cells() callback didn't have before this. It + doesn't matter much as it's rather useless now anyway (and will be + dropped). + What's more important however is that of_device_get_match_data() can + be used now thanks to owning a proper device pointer. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 4 +++- + drivers/nvmem/layouts/sl28vpd.c | 4 +++- + include/linux/nvmem-provider.h | 2 +- + 4 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -855,7 +855,7 @@ int nvmem_layout_register(struct nvmem_l + return -EINVAL; + + /* Populate the cells */ +- ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(layout); + if (ret) + return ret; + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,10 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) ++static int onie_tlv_parse_table(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; + u8 *table, *data; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,10 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) ++static int sl28vpd_add_cells(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; + struct device_node *layout_np; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -173,7 +173,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + struct device dev; + struct nvmem_device *nvmem; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++ int (*add_cells)(struct nvmem_layout *layout); + }; + + struct nvmem_layout_driver { diff --git a/target/linux/generic/backport-5.15/834-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch b/target/linux/generic/backport-5.15/834-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch new file mode 100644 index 0000000000..514b5f2de5 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch @@ -0,0 +1,72 @@ +From 43f60e3fb62edc7bd8891de8779fb422f4ae23ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:04 +0100 +Subject: [PATCH] nvmem: drop nvmem_layout_get_match_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Thanks for layouts refactoring we now have "struct device" associated +with layout. Also its OF pointer points directly to the "nvmem-layout" +DT node. + +All it takes to get match data is a generic of_device_get_match_data(). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 ------------- + include/linux/nvmem-provider.h | 10 ---------- + 2 files changed, 23 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -877,19 +877,6 @@ void nvmem_layout_unregister(struct nvme + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- struct device_node __maybe_unused *layout_np; +- const struct of_device_id *match; +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->dev.driver->of_match_table, layout_np); +- +- return match ? match->data : NULL; +-} +-EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); +- + /** + * nvmem_register() - Register a nvmem device for given nvmem_config. + * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -205,9 +205,6 @@ void nvmem_layout_driver_unregister(stru + module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ + nvmem_layout_driver_unregister) + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout); +- + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -238,13 +235,6 @@ static inline int nvmem_layout_register( + + static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} + +-static inline const void * +-nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- return NULL; +-} +- + #endif /* CONFIG_NVMEM */ + + #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) diff --git a/target/linux/generic/backport-5.15/834-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch b/target/linux/generic/backport-5.15/834-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch new file mode 100644 index 0000000000..aa0bbaa0c5 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch @@ -0,0 +1,53 @@ +From 33cf42e68efc8ff529a7eee08a4f0ba8c8d0a207 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:17 +0100 +Subject: [PATCH] nvmem: core: add nvmem_dev_size() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is required by layouts that need to read whole NVMEM content. It's +especially useful for NVMEM devices without hardcoded layout (like +U-Boot environment data block). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 +++++++++++++ + include/linux/nvmem-consumer.h | 1 + + 2 files changed, 14 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -2164,6 +2164,19 @@ const char *nvmem_dev_name(struct nvmem_ + } + EXPORT_SYMBOL_GPL(nvmem_dev_name); + ++/** ++ * nvmem_dev_size() - Get the size of a given nvmem device. ++ * ++ * @nvmem: nvmem device. ++ * ++ * Return: size of the nvmem device. ++ */ ++size_t nvmem_dev_size(struct nvmem_device *nvmem) ++{ ++ return nvmem->size; ++} ++EXPORT_SYMBOL_GPL(nvmem_dev_size); ++ + static int __init nvmem_init(void) + { + int ret; +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -81,6 +81,7 @@ int nvmem_device_cell_write(struct nvmem + struct nvmem_cell_info *info, void *buf); + + const char *nvmem_dev_name(struct nvmem_device *nvmem); ++size_t nvmem_dev_size(struct nvmem_device *nvmem); + + void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, + size_t nentries); diff --git a/target/linux/generic/backport-5.15/834-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch b/target/linux/generic/backport-5.15/834-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch new file mode 100644 index 0000000000..fc826f3f7e --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch @@ -0,0 +1,126 @@ +From 7c8979b42b1a9c5604f431ba804928e55919263c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:18 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem_add_one_cell() nvmem subsystem + helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplify adding NVMEM cells. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-3-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 55 +++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 34 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -23,13 +23,10 @@ enum u_boot_env_format { + + struct u_boot_env { + struct device *dev; ++ struct nvmem_device *nvmem; + enum u_boot_env_format format; + + struct mtd_info *mtd; +- +- /* Cells */ +- struct nvmem_cell_info *cells; +- int ncells; + }; + + struct u_boot_env_image_single { +@@ -94,43 +91,36 @@ static int u_boot_env_read_post_process_ + static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + char *data = buf + data_offset; + char *var, *value, *eq; +- int idx; +- +- priv->ncells = 0; +- for (var = data; var < data + data_len && *var; var += strlen(var) + 1) +- priv->ncells++; +- +- priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; + +- for (var = data, idx = 0; ++ for (var = data; + var < data + data_len && *var; +- var = value + strlen(value) + 1, idx++) { ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) + return -ENOMEM; +- priv->cells[idx].offset = data_offset + value - data; +- priv->cells[idx].bytes = strlen(value); +- priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); + if (!strcmp(var, "ethaddr")) { +- priv->cells[idx].raw_len = strlen(value); +- priv->cells[idx].bytes = ETH_ALEN; +- priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; + } +- } + +- if (WARN_ON(idx != priv->ncells)) +- priv->ncells = idx; ++ nvmem_add_one_cell(nvmem, &info); ++ } + + return 0; + } +@@ -209,7 +199,6 @@ static int u_boot_env_probe(struct platf + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct u_boot_env *priv; +- int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -224,17 +213,15 @@ static int u_boot_env_probe(struct platf + return PTR_ERR(priv->mtd); + } + +- err = u_boot_env_parse(priv); +- if (err) +- return err; +- + config.dev = dev; +- config.cells = priv->cells; +- config.ncells = priv->ncells; + config.priv = priv; + config.size = priv->mtd->size; + +- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++ priv->nvmem = devm_nvmem_register(dev, &config); ++ if (IS_ERR(priv->nvmem)) ++ return PTR_ERR(priv->nvmem); ++ ++ return u_boot_env_parse(priv); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/backport-5.15/834-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch b/target/linux/generic/backport-5.15/834-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch new file mode 100644 index 0000000000..70abc7cf14 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch @@ -0,0 +1,81 @@ +From a832556d23c5a11115f300011a5874d6107a0d62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:19 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem device helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use nvmem_dev_size() and nvmem_device_read() to make this driver less +mtd dependent. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-4-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -127,27 +127,34 @@ static int u_boot_env_add_cells(struct u + + static int u_boot_env_parse(struct u_boot_env *priv) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + size_t data_offset; + size_t data_len; ++ size_t dev_size; + uint32_t crc32; + uint32_t calc; +- size_t bytes; + uint8_t *buf; ++ int bytes; + int err; + +- buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kcalloc(1, dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + +- err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); +- if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { +- dev_err(dev, "Failed to read from mtd: %d\n", err); ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; + goto err_kfree; + } + +@@ -169,8 +176,8 @@ static int u_boot_env_parse(struct u_boo + break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); +- crc32_data_len = priv->mtd->size - crc32_data_offset; +- data_len = priv->mtd->size - data_offset; ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { +@@ -179,7 +186,7 @@ static int u_boot_env_parse(struct u_boo + goto err_kfree; + } + +- buf[priv->mtd->size - 1] = '\0'; ++ buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); + if (err) + dev_err(dev, "Failed to add cells: %d\n", err); diff --git a/target/linux/generic/backport-5.15/834-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch b/target/linux/generic/backport-5.15/834-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch new file mode 100644 index 0000000000..273cfed874 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch @@ -0,0 +1,62 @@ +From 6bafe07c930676d6430be471310958070816a595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:20 +0100 +Subject: [PATCH] nvmem: u-boot-env: improve coding style +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Prefer kzalloc() over kcalloc() + See memory-allocation.rst which says: "to be on the safe side it's + best to use routines that set memory to zero, like kzalloc()" +2. Drop dev_err() for u_boot_env_add_cells() fail + It can fail only on -ENOMEM. We don't want to print error then. +3. Add extra "crc32_addr" variable + It makes code reading header's crc32 easier to understand / review. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-5-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -132,6 +132,7 @@ static int u_boot_env_parse(struct u_boo + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; ++ __le32 *crc32_addr; + size_t data_offset; + size_t data_len; + size_t dev_size; +@@ -143,7 +144,7 @@ static int u_boot_env_parse(struct u_boo + + dev_size = nvmem_dev_size(nvmem); + +- buf = kcalloc(1, dev_size, GFP_KERNEL); ++ buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; +@@ -175,7 +176,8 @@ static int u_boot_env_parse(struct u_boo + data_offset = offsetof(struct u_boot_env_image_broadcom, data); + break; + } +- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + +@@ -188,8 +190,6 @@ static int u_boot_env_parse(struct u_boo + + buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- if (err) +- dev_err(dev, "Failed to add cells: %d\n", err); + + err_kfree: + kfree(buf); diff --git a/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch b/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch new file mode 100644 index 0000000000..283e226d16 --- /dev/null +++ b/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch @@ -0,0 +1,139 @@ +From mboxrd@z Thu Jan 1 00:00:00 1970 +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sMUeie/T" +Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84BB8D6D + for ; Wed, 6 Dec 2023 15:16:16 -0800 (PST) +Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-db5416d0fccso403298276.1 + for ; Wed, 06 Dec 2023 15:16:16 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20230601; t=1701904575; x=1702509375; darn=vger.kernel.org; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=sMUeie/TxdytzC0EyT11QWi1TqTtiv7KCTs1F2vLmUUvPKNA3+1MHFo8ECW+0gQuDE + FGrgdZKGK5mXQgkF0N3JiSLvKO8tpQOIB57JLCG5IVy5dr2vVv0ExU3Dag2Cc4oBIBIO + w/cH95O1oPlvluIpATmAsxenVr7mFomU63BqYiRGLaEhWeb2hJ636GO8lubtsDfdFFoi + GPOL2tQwV93VnqmywBBpFaNAULN0UoCFhfkKv5prvpkXq19sWI7zyorVZ+rdTYem5m4T + dXsDaLXPtC3Dh2JOad1duSQIah/wCHYYUcV3IoFhwj2y0Uk/TTCrnZPORweSADcEy6Ho + vDrA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1701904575; x=1702509375; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=Dmc6aSntxPlxAk72zVO1G9WoZnFtLolxENlLscYYAHG3VE+PQ8gGN2rPzcGoKb2Btb + 4b0PvjOzSlPQyghahdhdlz04RtAeeGG/MkfNiYjFql5OifIoovb51kroiPYrVsa7Ps7Y + +Pxug0+NPdTm5s9TNz940ZKl3GRME8UTmVxpWJRX03XMOqb6Wgsh2SK9ahXKc4yRsi62 + 3a3J72WmmSgvimxwM/99fXwvoUQpiv2J1xCoqc1Ng4q4qSuZvzmHN7ZTGaUhLxOqLeLK + 3W4RKHW6rZ7UjppuB6I3NXW+D344By2rdKp1sRXpjdQ0GS3YUcvlRETcJBXJudHfQP5Y + CLOw== +X-Gm-Message-State: AOJu0YzdCTLdwny+N99zeMgyKqFsEZhfIhL2cbgKA6zC1U/OLkxxRLoM + XrYVBC9DmxCGmP4o+M/Z/kHUew/9faHlCiLGxw== +X-Google-Smtp-Source: AGHT+IFRXxBV6JuX5Cl/k2o1+WKkCwkR8j20MJSkmoGCedPAtqFttH8OVh1/6vdfnq8MPN++A2h89peZQhyG8OsJ8A== +X-Received: from jstitt-linux1.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:23b5]) + (user=justinstitt job=sendgmr) by 2002:a25:dac7:0:b0:da0:3117:f35 with SMTP + id n190-20020a25dac7000000b00da031170f35mr28652ybf.3.1701904575576; Wed, 06 + Dec 2023 15:16:15 -0800 (PST) +Date: Wed, 06 Dec 2023 23:16:10 +0000 +In-Reply-To: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +Precedence: bulk +X-Mailing-List: bpf@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +Mime-Version: 1.0 +References: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +X-Developer-Key: i=justinstitt@google.com; a=ed25519; pk=tC3hNkJQTpNX/gLKxTNQKDmiQl6QjBNCGKJINqAdJsE= +X-Developer-Signature: v=1; a=ed25519-sha256; t=1701904573; l=1840; + i=justinstitt@google.com; s=20230717; h=from:subject:message-id; + bh=UMdetIL2ZsPIkSodqhw2fM21NHJVjCu0lRImFuNhVoM=; b=a8rMnXfVVQ5gsxHWG4WRMwOLxZgflqXZtNuKx26vv4DwYvvCtCiYjl3f1frOjV/Ul2kaxq5g/ + b/UOv678JKCDASVokxG5GJifAnU7/kqRxdhcwfRkrD8RUfcsmiZOfyF +X-Mailer: b4 0.12.3 +Message-ID: <20231206-ethtool_puts_impl-v5-1-5a2528e17bf8@google.com> +Subject: [PATCH net-next v5 1/3] ethtool: Implement ethtool_puts() +From: justinstitt@google.com +To: "David S. Miller" , Eric Dumazet , + Jakub Kicinski , Paolo Abeni , Shay Agroskin , + Arthur Kiyanovski , David Arinzon , Noam Dagan , + Saeed Bishara , Rasesh Mody , + Sudarsana Kalluru , GR-Linux-NIC-Dev@marvell.com, + Dimitris Michailidis , Yisen Zhuang , + Salil Mehta , Jesse Brandeburg , + Tony Nguyen , Louis Peens , + Shannon Nelson , Brett Creeley , drivers@pensando.io, + "K. Y. Srinivasan" , Haiyang Zhang , Wei Liu , + Dexuan Cui , Ronak Doshi , + VMware PV-Drivers Reviewers , Andy Whitcroft , Joe Perches , + Dwaipayan Ray , Lukas Bulwahn , + Hauke Mehrtens , Andrew Lunn , + Florian Fainelli , Vladimir Oltean , + "=?utf-8?q?Ar=C4=B1n=C3=A7_=C3=9CNAL?=" , Daniel Golle , + Landen Chao , DENG Qingfang , + Sean Wang , Matthias Brugger , + AngeloGioacchino Del Regno , + Linus Walleij , + "=?utf-8?q?Alvin_=C5=A0ipraga?=" , Wei Fang , + Shenwei Wang , Clark Wang , + NXP Linux Team , Lars Povlsen , + Steen Hegelund , Daniel Machon , + UNGLinuxDriver@microchip.com, Jiawen Wu , + Mengyuan Lou , Heiner Kallweit , + Russell King , Alexei Starovoitov , + Daniel Borkmann , Jesper Dangaard Brouer , + John Fastabend +Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, + Nick Desaulniers , Nathan Chancellor , + Kees Cook , intel-wired-lan@lists.osuosl.org, + oss-drivers@corigine.com, linux-hyperv@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, + bpf@vger.kernel.org, Justin Stitt +Content-Type: text/plain; charset="utf-8" + +Use strscpy() to implement ethtool_puts(). + +Functionally the same as ethtool_sprintf() when it's used with two +arguments or with just "%s" format specifier. + +Signed-off-by: Justin Stitt +--- + include/linux/ethtool.h | 13 +++++++++++++ + net/ethtool/ioctl.c | 7 +++++++ + 2 files changed, 20 insertions(+) + +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -788,4 +788,17 @@ int ethtool_get_phc_vclocks(struct net_d + * next string. + */ + extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...); ++ ++/** ++ * ethtool_puts - Write string to ethtool string data ++ * @data: Pointer to a pointer to the start of string to update ++ * @str: String to write ++ * ++ * Write string to *data without a trailing newline. Update *data ++ * to point at start of next string. ++ * ++ * Prefer this function to ethtool_sprintf() when given only ++ * two arguments or if @fmt is just "%s". ++ */ ++extern void ethtool_puts(u8 **data, const char *str); + #endif /* _LINUX_ETHTOOL_H */ +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1954,6 +1954,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * + } + EXPORT_SYMBOL(ethtool_sprintf); + ++void ethtool_puts(u8 **data, const char *str) ++{ ++ strscpy(*data, str, ETH_GSTRING_LEN); ++ *data += ETH_GSTRING_LEN; ++} ++EXPORT_SYMBOL(ethtool_puts); ++ + static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) + { + struct ethtool_value id; diff --git a/target/linux/generic/backport-6.1/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch b/target/linux/generic/backport-6.1/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch new file mode 100644 index 0000000000..2e6d881fe9 --- /dev/null +++ b/target/linux/generic/backport-6.1/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch @@ -0,0 +1,58 @@ +From e2192de59e457aef8d1f055a452131f0b3e5d097 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 18 Jan 2023 14:26:53 +0100 +Subject: [PATCH] bitfield: add FIELD_PREP_CONST() + +Neither FIELD_PREP() nor *_encode_bits() can be used +in constant contexts (such as initializers), but we +don't want to define shift constants for all masks +just for use in initializers, and having checks that +the values fit is also useful. + +Therefore, add FIELD_PREP_CONST() which is a smaller +version of FIELD_PREP() that can only take constant +arguments and has less friendly (but not less strict) +error checks, and expands to a constant value. + +Signed-off-by: Johannes Berg +Link: https://lore.kernel.org/r/20230118142652.53f20593504b.Iaeea0aee77a6493d70e573b4aa55c91c00e01e4b@changeid +Signed-off-by: Johannes Berg +--- + include/linux/bitfield.h | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/include/linux/bitfield.h ++++ b/include/linux/bitfield.h +@@ -115,6 +115,32 @@ + ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ + }) + ++#define __BF_CHECK_POW2(n) BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0) ++ ++/** ++ * FIELD_PREP_CONST() - prepare a constant bitfield element ++ * @_mask: shifted mask defining the field's length and position ++ * @_val: value to put in the field ++ * ++ * FIELD_PREP_CONST() masks and shifts up the value. The result should ++ * be combined with other fields of the bitfield using logical OR. ++ * ++ * Unlike FIELD_PREP() this is a constant expression and can therefore ++ * be used in initializers. Error checking is less comfortable for this ++ * version, and non-constant masks cannot be used. ++ */ ++#define FIELD_PREP_CONST(_mask, _val) \ ++ ( \ ++ /* mask must be non-zero */ \ ++ BUILD_BUG_ON_ZERO((_mask) == 0) + \ ++ /* check if value fits */ \ ++ BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \ ++ /* check if mask is contiguous */ \ ++ __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) + \ ++ /* and create the value */ \ ++ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \ ++ ) ++ + /** + * FIELD_GET() - extract a bitfield element + * @_mask: shifted mask defining the field's length and position diff --git a/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch b/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch new file mode 100644 index 0000000000..ff186742ba --- /dev/null +++ b/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch @@ -0,0 +1,326 @@ +From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 9 Jan 2023 16:30:41 +0100 +Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers + +Currently C22 and C45 transactions are mixed over a combined API calls +which make use of a special bit in the reg address to indicate if a +C45 transaction should be performed. This makes it impossible to know +if the bus driver actually supports C45. Additionally, many C22 only +drivers don't return -EOPNOTSUPP when asked to perform a C45 +transaction, they mistaking perform a C22 transaction. + +This is the first step to cleanly separate C22 from C45. To maintain +backwards compatibility until all drivers which are capable of +performing C45 are converted to this new API, the helper functions +will fall back to the older API if the new API is not +supported. Eventually this fallback will be removed. + +Signed-off-by: Andrew Lunn +Signed-off-by: Michael Walle +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++ + include/linux/mdio.h | 39 ++++---- + include/linux/phy.h | 5 + + 3 files changed, 214 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_ + EXPORT_SYMBOL_GPL(__mdiobus_modify_changed); + + /** ++ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * Read a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->read_c45) ++ retval = bus->read_c45(bus, addr, devad, regnum); ++ else ++ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum)); ++ ++ trace_mdio_access(bus, 1, addr, regnum, retval, retval); ++ mdiobus_stats_acct(&bus->stats[addr], true, retval); ++ ++ return retval; ++} ++EXPORT_SYMBOL(__mdiobus_c45_read); ++ ++/** ++ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * Write a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->write_c45) ++ err = bus->write_c45(bus, addr, devad, regnum, val); ++ else ++ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum), ++ val); ++ ++ trace_mdio_access(bus, 0, addr, regnum, val, err); ++ mdiobus_stats_acct(&bus->stats[addr], false, err); ++ ++ return err; ++} ++EXPORT_SYMBOL(__mdiobus_c45_write); ++ ++/** ++ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to modify ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * Read, modify, and if any change, write the register value back to the ++ * device. Any error returns a negative number. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, ++ int devad, u32 regnum, u16 mask, ++ u16 set) ++{ ++ int new, ret; ++ ++ ret = __mdiobus_c45_read(bus, addr, devad, regnum); ++ if (ret < 0) ++ return ret; ++ ++ new = (ret & ~mask) | set; ++ if (new == ret) ++ return 0; ++ ++ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new); ++ ++ return ret < 0 ? ret : 1; ++} ++ ++/** + * mdiobus_read_nested - Nested version of the mdiobus_read function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in + EXPORT_SYMBOL(mdiobus_read); + + /** ++ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ mutex_lock(&bus->mdio_lock); ++ retval = __mdiobus_c45_read(bus, addr, devad, regnum); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return retval; ++} ++EXPORT_SYMBOL(mdiobus_c45_read); ++ ++/** + * mdiobus_write_nested - Nested version of the mdiobus_write function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i + EXPORT_SYMBOL(mdiobus_write); + + /** ++ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_write(bus, addr, devad, regnum, val); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL(mdiobus_c45_write); ++ ++/** + * mdiobus_modify - Convenience function for modifying a given mdio device + * register + * @bus: the mii_bus struct +@@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus, + EXPORT_SYMBOL_GPL(mdiobus_modify); + + /** ++ * mdiobus_c45_modify - Convenience function for modifying a given mdio device ++ * register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, ++ mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err < 0 ? err : 0; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify); ++ ++/** + * mdiobus_modify_changed - Convenience function for modifying a given mdio + * device register and returning if it changed + * @bus: the mii_bus struct +@@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu + EXPORT_SYMBOL_GPL(mdiobus_modify_changed); + + /** ++ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio ++ * device register and returning if it changed ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr, ++ u32 regnum, u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed); ++ ++/** + * mdio_bus_match - determine if given MDIO driver supports the given + * MDIO device + * @dev: target MDIO device +--- a/include/linux/mdio.h ++++ b/include/linux/mdio.h +@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus, + u16 set); + int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, + u16 mask, u16 set); ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set); ++ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, ++ u32 regnum, u16 mask, u16 set); + + static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) + { +@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32 + return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); + } + +-static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) +-{ +- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); +-} +- +-static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) +-{ +- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), +- val); +-} +- +-static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) ++static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad, ++ u32 regnum, u16 mask, u16 set) + { +- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); ++ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum, ++ mask, set); + } + +-static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) ++static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev, ++ int devad, u32 regnum, u16 mask, ++ u16 set) + { +- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val); ++ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad, ++ regnum, mask, set); + } + + int mdiobus_register_device(struct mdio_device *mdiodev); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -364,6 +364,11 @@ struct mii_bus { + int (*read)(struct mii_bus *bus, int addr, int regnum); + /** @write: Perform a write transfer on the bus */ + int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); ++ /** @read_c45: Perform a C45 read transfer on the bus */ ++ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum); ++ /** @write_c45: Perform a C45 write transfer on the bus */ ++ int (*write_c45)(struct mii_bus *bus, int addr, int devnum, ++ int regnum, u16 val); + /** @reset: Perform a reset of the bus */ + int (*reset)(struct mii_bus *bus); + diff --git a/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch similarity index 91% rename from target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch rename to target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch index a28394f629..80210e6da1 100644 --- a/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch +++ b/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch @@ -52,7 +52,7 @@ Signed-off-by: David S. Miller return 0; --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -192,6 +192,7 @@ static int phylink_interface_max_speed(p +@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII: @@ -60,7 +60,7 @@ Signed-off-by: David S. Miller case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_QUSGMII: case PHY_INTERFACE_MODE_SGMII: -@@ -453,6 +454,7 @@ unsigned long phylink_get_capabilities(p +@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII: @@ -68,7 +68,7 @@ Signed-off-by: David S. Miller case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_QUSGMII: case PHY_INTERFACE_MODE_SGMII: -@@ -819,6 +821,7 @@ static int phylink_parse_mode(struct phy +@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy switch (pl->link_config.interface) { case PHY_INTERFACE_MODE_SGMII: @@ -78,7 +78,7 @@ Signed-off-by: David S. Miller case PHY_INTERFACE_MODE_RGMII: --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -104,6 +104,7 @@ extern const int phy_10gbit_features_arr +@@ -103,6 +103,7 @@ extern const int phy_10gbit_features_arr * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax @@ -86,7 +86,7 @@ Signed-off-by: David S. Miller * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX -@@ -141,6 +142,7 @@ typedef enum { +@@ -140,6 +141,7 @@ typedef enum { PHY_INTERFACE_MODE_XGMII, PHY_INTERFACE_MODE_XLGMII, PHY_INTERFACE_MODE_MOCA, @@ -94,7 +94,7 @@ Signed-off-by: David S. Miller PHY_INTERFACE_MODE_QSGMII, PHY_INTERFACE_MODE_TRGMII, PHY_INTERFACE_MODE_100BASEX, -@@ -248,6 +250,8 @@ static inline const char *phy_modes(phy_ +@@ -247,6 +249,8 @@ static inline const char *phy_modes(phy_ return "xlgmii"; case PHY_INTERFACE_MODE_MOCA: return "moca"; diff --git a/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch b/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch new file mode 100644 index 0000000000..7cacb71b18 --- /dev/null +++ b/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch @@ -0,0 +1,32 @@ +From a593a2fcfdfb92cfd0ffc54bc81b07e6bfaaaf46 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Thu, 16 Mar 2023 14:08:26 +0200 +Subject: [PATCH] net: phy: at803x: Replace of_gpio.h with what indeed is used + +of_gpio.h in this driver is solely used as a proxy to other headers. +This is incorrect usage of the of_gpio.h. Replace it .h with what +indeed is used in the code. + +Signed-off-by: Andy Shevchenko +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -13,12 +13,11 @@ + #include + #include + #include +-#include + #include +-#include + #include + #include + #include ++#include + #include + #include + #include diff --git a/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch b/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch new file mode 100644 index 0000000000..dab4928960 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch @@ -0,0 +1,70 @@ +From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:19 +0800 +Subject: [PATCH 1/6] net: phy: at803x: support qca8081 + genphy_c45_pma_read_abilities + +qca8081 PHY supports to use genphy_c45_pma_read_abilities for +getting the PHY features supported except for the autoneg ability + +but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it +manually after calling genphy_c45_pma_read_abilities. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -902,15 +902,6 @@ static int at803x_get_features(struct ph + if (err) + return err; + +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); +- if (err < 0) +- return err; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, +- err & MDIO_PMA_NG_EXTABLE_2_5GBT); +- } +- + if (phydev->drv->phy_id != ATH8031_PHY_ID) + return 0; + +@@ -1996,6 +1987,23 @@ static int qca808x_cable_test_get_status + return 0; + } + ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ return 0; ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2163,7 +2171,7 @@ static struct phy_driver at803x_driver[] + .set_tunable = at803x_set_tunable, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, +- .get_features = at803x_get_features, ++ .get_features = qca808x_get_features, + .config_aneg = at803x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, diff --git a/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch b/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch new file mode 100644 index 0000000000..28874068ce --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch @@ -0,0 +1,73 @@ +From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:20 +0800 +Subject: [PATCH 2/6] net: phy: at803x: merge qca8081 slave seed function + +merge the seed enablement and seed value configuration into +one function, since the random seed value is needed to be +configured when the seed is enabled. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1730,24 +1730,19 @@ static int qca808x_phy_fast_retrain_conf + return 0; + } + +-static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) +-{ +- u16 seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); +-} +- + static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) + { +- u16 seed_enable = 0; ++ u16 seed_value; + +- if (enable) +- seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); + ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + + static int qca808x_config_init(struct phy_device *phydev) +@@ -1771,12 +1766,7 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_random_seed_set(phydev); +- if (ret) +- return ret; +- +- /* Enable seed */ ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ + ret = qca808x_phy_ms_seed_enable(phydev, true); + if (ret) + return ret; +@@ -1821,7 +1811,6 @@ static int qca808x_read_status(struct ph + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { +- qca808x_phy_ms_random_seed_set(phydev); + qca808x_phy_ms_seed_enable(phydev, true); + } + } diff --git a/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch b/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch new file mode 100644 index 0000000000..b91d2cab30 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch @@ -0,0 +1,76 @@ +From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:21 +0800 +Subject: [PATCH 3/6] net: phy: at803x: enable qca8081 slave seed conditionally + +qca8081 is the single port PHY, the slave prefer mode is used +by default. + +if the phy master perfer mode is configured, the slave seed +configuration should not be enabled, since the slave seed +enablement is for making PHY linked as slave mode easily. + +disable slave seed if the master mode is preferred. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1745,6 +1745,12 @@ static int qca808x_phy_ms_seed_enable(st + QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1766,11 +1772,17 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) + return ret; + ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); +@@ -1802,13 +1814,16 @@ static int qca808x_read_status(struct ph + phydev->interface = PHY_INTERFACE_MODE_SGMII; + } else { + /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected. ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * + * the reason for not putting this code into the function link_change_notify is + * the corner case where the link partner is also the qca8081 PHY and the seed + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); diff --git a/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch b/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch new file mode 100644 index 0000000000..b8db89d853 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch @@ -0,0 +1,48 @@ +From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:22 +0800 +Subject: [PATCH 4/6] net: phy: at803x: support qca8081 1G chip type + +The qca8081 1G chip version does not support 2.5 capability, which +is distinguished from qca8081 2.5G chip according to the bit0 of +register mmd7.0x901d, the 1G version chip also has the same PHY ID +as the normal qca8081 2.5G chip. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -272,6 +272,10 @@ + #define QCA808X_CDT_STATUS_STAT_OPEN 2 + #define QCA808X_CDT_STATUS_STAT_SHORT 3 + ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2005,6 +2009,17 @@ static int qca808x_get_features(struct p + */ + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch b/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch new file mode 100644 index 0000000000..b54a86e5f5 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch @@ -0,0 +1,98 @@ +From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:23 +0800 +Subject: [PATCH 5/6] net: phy: at803x: remove qca8081 1G fast retrain and + slave seed config + +The fast retrain and slave seed configs are only applicable when the 2.5G +ability is supported. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1755,6 +1755,11 @@ static bool qca808x_is_prefer_master(str + (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); + } + ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1771,20 +1776,24 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); + if (ret) + return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } + } + + /* Configure adc threshold as 100mv for the link 10M */ +@@ -1826,11 +1835,13 @@ static int qca808x_read_status(struct ph + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } + } + } + +@@ -1845,7 +1856,10 @@ static int qca808x_soft_reset(struct phy + if (ret < 0) + return ret; + +- return qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; + } + + static bool qca808x_cdt_fault_length_valid(int cdt_code) diff --git a/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch b/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch new file mode 100644 index 0000000000..e382cf7876 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch @@ -0,0 +1,55 @@ +From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:24 +0800 +Subject: [PATCH 6/6] net: phy: at803x: add qca8081 fifo reset on the link + changed + +The qca8081 sgmii fifo needs to be reset on link down and +released on the link up in case of any abnormal issue +such as the packet blocked on the PHY. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -276,6 +276,9 @@ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d + #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) + ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2037,6 +2040,16 @@ static int qca808x_get_features(struct p + return 0; + } + ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2213,6 +2226,7 @@ static struct phy_driver at803x_driver[] + .soft_reset = qca808x_soft_reset, + .cable_test_start = qca808x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, + }, }; + + module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-6.1/707-v6.8-01-net-phy-at803x-fix-passing-the-wrong-reference-for-c.patch b/target/linux/generic/backport-6.1/707-v6.8-01-net-phy-at803x-fix-passing-the-wrong-reference-for-c.patch new file mode 100644 index 0000000000..b206b18052 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-01-net-phy-at803x-fix-passing-the-wrong-reference-for-c.patch @@ -0,0 +1,45 @@ +From f8fdbf3389f44c7026f16e36cb1f2ff017f7f5b2 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:48 +0100 +Subject: [PATCH 01/13] net: phy: at803x: fix passing the wrong reference for + config_intr + +Fix passing the wrong reference for config_initr on passing the function +pointer, drop the wrong & from at803x_config_intr in the PHY struct. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -2104,7 +2104,7 @@ static struct phy_driver at803x_driver[] + .write_page = at803x_write_page, + .get_features = at803x_get_features, + .read_status = at803x_read_status, +- .config_intr = &at803x_config_intr, ++ .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +@@ -2134,7 +2134,7 @@ static struct phy_driver at803x_driver[] + .resume = at803x_resume, + .flags = PHY_POLL_CABLE_TEST, + /* PHY_BASIC_FEATURES */ +- .config_intr = &at803x_config_intr, ++ .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, + .cable_test_get_status = at803x_cable_test_get_status, +@@ -2150,7 +2150,7 @@ static struct phy_driver at803x_driver[] + .resume = at803x_resume, + .flags = PHY_POLL_CABLE_TEST, + /* PHY_BASIC_FEATURES */ +- .config_intr = &at803x_config_intr, ++ .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, + .cable_test_get_status = at803x_cable_test_get_status, diff --git a/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch b/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch new file mode 100644 index 0000000000..eb9172b1cc --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch @@ -0,0 +1,69 @@ +From 6a3b8c573b5a152a6aa7a0b54c5e18b84c6ba6f5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:49 +0100 +Subject: [PATCH 02/13] net: phy: at803x: move disable WOL to specific at8031 + probe + +Move the WOL disable call to specific at8031 probe to make at803x_probe +more generic and drop extra check for PHY ID. + +Keep the same previous behaviour by first calling at803x_probe and then +disabling WOL. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -886,15 +886,6 @@ static int at803x_probe(struct phy_devic + priv->is_fiber = true; + break; + } +- +- /* Disable WoL in 1588 register which is enabled +- * by default +- */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; + } + + return 0; +@@ -1591,6 +1582,22 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ /* Disable WoL in 1588 register which is enabled ++ * by default ++ */ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2092,7 +2099,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8031_probe, + .config_init = at803x_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, diff --git a/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch b/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch new file mode 100644 index 0000000000..5a9d1764f1 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch @@ -0,0 +1,129 @@ +From 07b1ad83b9ed6db1735ba10baf67b7a565ac0cef Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:50 +0100 +Subject: [PATCH 03/13] net: phy: at803x: raname hw_stats functions to qca83xx + specific name + +The function and the struct related to hw_stats were specific to qca83xx +PHY but were called following the convention in the driver of calling +everything with at803x prefix. + +To better organize the code, rename these function a more specific name +to better describe that they are specific to 83xx PHY family. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 44 ++++++++++++++++++++-------------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -295,7 +295,7 @@ struct at803x_hw_stat { + enum stat_access_type access_type; + }; + +-static struct at803x_hw_stat at803x_hw_stats[] = { ++static struct at803x_hw_stat qca83xx_hw_stats[] = { + { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, + { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +@@ -311,7 +311,7 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(at803x_hw_stats)]; ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; + }; + + struct at803x_context { +@@ -529,24 +529,24 @@ static void at803x_get_wol(struct phy_de + wol->wolopts |= WAKE_MAGIC; + } + +-static int at803x_get_sset_count(struct phy_device *phydev) ++static int qca83xx_get_sset_count(struct phy_device *phydev) + { +- return ARRAY_SIZE(at803x_hw_stats); ++ return ARRAY_SIZE(qca83xx_hw_stats); + } + +-static void at803x_get_strings(struct phy_device *phydev, u8 *data) ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) { ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { + strscpy(data + i * ETH_GSTRING_LEN, +- at803x_hw_stats[i].string, ETH_GSTRING_LEN); ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); + } + } + +-static u64 at803x_get_stat(struct phy_device *phydev, int i) ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) + { +- struct at803x_hw_stat stat = at803x_hw_stats[i]; ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; + struct at803x_priv *priv = phydev->priv; + int val; + u64 ret; +@@ -567,13 +567,13 @@ static u64 at803x_get_stat(struct phy_de + return ret; + } + +-static void at803x_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) +- data[i] = at803x_get_stat(phydev, i); ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); + } + + static int at803x_suspend(struct phy_device *phydev) +@@ -2175,9 +2175,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2191,9 +2191,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2207,9 +2207,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { diff --git a/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch b/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch new file mode 100644 index 0000000000..f09142c5ed --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch @@ -0,0 +1,155 @@ +From d43cff3f82336c0bd965ea552232d9f4ddac71a6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:51 +0100 +Subject: [PATCH 04/13] net: phy: at803x: move qca83xx specific check in + dedicated functions + +Rework qca83xx specific check to dedicated function to tidy things up +and drop useless phy_id check. + +Also drop an useless link_change_notify for QCA8337 as it did nothing an +returned early. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 68 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1623,27 +1623,26 @@ static int qca83xx_config_init(struct ph + break; + } + ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ + /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. + * Disable on init and enable only with 100m speed following + * qca original source code. + */ +- if (phydev->drv->phy_id == QCA8327_A_PHY_ID || +- phydev->drv->phy_id == QCA8327_B_PHY_ID) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); + +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; ++ return qca83xx_config_init(phydev); + } + + static void qca83xx_link_change_notify(struct phy_device *phydev) + { +- /* QCA8337 doesn't require DAC Amplitude adjustement */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) +- return; +- + /* Set DAC Amplitude adjustment to +6% for 100m on link running */ + if (phydev->state == PHY_RUNNING) { + if (phydev->speed == SPEED_100) +@@ -1686,19 +1685,6 @@ static int qca83xx_resume(struct phy_dev + + static int qca83xx_suspend(struct phy_device *phydev) + { +- u16 mask = 0; +- +- /* Only QCA8337 support actual suspend. +- * QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) { +- genphy_suspend(phydev); +- } else { +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- } +- + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, + AT803X_DEBUG_GATE_CLK_IN1000, 0); + +@@ -1709,6 +1695,27 @@ static int qca83xx_suspend(struct phy_de + return 0; + } + ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ + static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) + { + int ret; +@@ -2170,7 +2177,6 @@ static struct phy_driver at803x_driver[] + .phy_id_mask = QCA8K_PHY_ID_MASK, + .name = "Qualcomm Atheros 8337 internal PHY", + /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, +@@ -2178,7 +2184,7 @@ static struct phy_driver at803x_driver[] + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8337_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-A from switch QCA8327-AL1A */ +@@ -2189,12 +2195,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-B from switch QCA8327-BL1A */ +@@ -2205,12 +2211,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* Qualcomm QCA8081 */ diff --git a/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch b/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch new file mode 100644 index 0000000000..a5cc67a8c8 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch @@ -0,0 +1,94 @@ +From 900eef75cc5018e149c52fe305c9c3fe424c52a7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:52 +0100 +Subject: [PATCH 05/13] net: phy: at803x: move specific DT option for at8031 to + specific probe + +Move specific DT options for at8031 to specific probe to tidy things up +and make at803x_parse_dt more generic. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 55 ++++++++++++++++++++++------------------ + 1 file changed, 31 insertions(+), 24 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -825,30 +825,6 @@ static int at803x_parse_dt(struct phy_de + } + } + +- /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping +- * options. +- */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- if (of_property_read_bool(node, "qca,keep-pll-enabled")) +- priv->flags |= AT803X_KEEP_PLL_ENABLED; +- +- ret = at8031_register_regulators(phydev); +- if (ret < 0) +- return ret; +- +- ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, +- "vddio"); +- if (ret) { +- phydev_err(phydev, "failed to get VDDIO regulator\n"); +- return ret; +- } +- +- /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- ret = phy_sfp_probe(phydev, &at803x_sfp_ops); +- if (ret < 0) +- return ret; +- } +- + return 0; + } + +@@ -1582,6 +1558,30 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ if (of_property_read_bool(node, "qca,keep-pll-enabled")) ++ priv->flags |= AT803X_KEEP_PLL_ENABLED; ++ ++ ret = at8031_register_regulators(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, ++ "vddio"); ++ if (ret) { ++ phydev_err(phydev, "failed to get VDDIO regulator\n"); ++ return ret; ++ } ++ ++ /* Only AR8031/8033 support 1000Base-X for SFP modules */ ++ return phy_sfp_probe(phydev, &at803x_sfp_ops); ++} ++ + static int at8031_probe(struct phy_device *phydev) + { + int ret; +@@ -1590,6 +1590,13 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping ++ * options. ++ */ ++ ret = at8031_parse_dt(phydev); ++ if (ret) ++ return ret; ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch b/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch new file mode 100644 index 0000000000..9e10e000e5 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch @@ -0,0 +1,78 @@ +From 25d2ba94005fac18fe68878cddff59a67e115554 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:53 +0100 +Subject: [PATCH 06/13] net: phy: at803x: move specific at8031 probe mode check + to dedicated probe + +Move specific at8031 probe mode check to dedicated probe to make +at803x_probe more generic and keep code tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 39 +++++++++++++++++++-------------------- + 1 file changed, 19 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -844,26 +844,6 @@ static int at803x_probe(struct phy_devic + if (ret) + return ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- int mode_cfg; +- +- if (ccr < 0) +- return ccr; +- mode_cfg = ccr & AT803X_MODE_CFG_MASK; +- +- switch (mode_cfg) { +- case AT803X_MODE_CFG_BX1000_RGMII_50OHM: +- case AT803X_MODE_CFG_BX1000_RGMII_75OHM: +- priv->is_1000basex = true; +- fallthrough; +- case AT803X_MODE_CFG_FX100_RGMII_50OHM: +- case AT803X_MODE_CFG_FX100_RGMII_75OHM: +- priv->is_fiber = true; +- break; +- } +- } +- + return 0; + } + +@@ -1584,6 +1564,9 @@ static int at8031_parse_dt(struct phy_de + + static int at8031_probe(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; ++ int mode_cfg; ++ int ccr; + int ret; + + ret = at803x_probe(phydev); +@@ -1597,6 +1580,22 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ if (ccr < 0) ++ return ccr; ++ mode_cfg = ccr & AT803X_MODE_CFG_MASK; ++ ++ switch (mode_cfg) { ++ case AT803X_MODE_CFG_BX1000_RGMII_50OHM: ++ case AT803X_MODE_CFG_BX1000_RGMII_75OHM: ++ priv->is_1000basex = true; ++ fallthrough; ++ case AT803X_MODE_CFG_FX100_RGMII_50OHM: ++ case AT803X_MODE_CFG_FX100_RGMII_75OHM: ++ priv->is_fiber = true; ++ break; ++ } ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch b/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch new file mode 100644 index 0000000000..c9ef6df827 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch @@ -0,0 +1,86 @@ +From 3ae3bc426eaf57ca8f53d75777d9a5ef779bc7b7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:54 +0100 +Subject: [PATCH 07/13] net: phy: at803x: move specific at8031 config_init to + dedicated function + +Move specific at8031 config_init to dedicated function to make +at803x_config_init more generic and tidy things up. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 45 ++++++++++++++++++++++------------------ + 1 file changed, 25 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -951,27 +951,8 @@ static int at803x_hibernation_mode_confi + + static int at803x_config_init(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- /* Some bootloaders leave the fiber page selected. +- * Switch to the appropriate page (fiber or copper), as otherwise we +- * read the PHY capabilities from the wrong page. +- */ +- phy_lock_mdio_bus(phydev); +- ret = at803x_write_page(phydev, +- priv->is_fiber ? AT803X_PAGE_FIBER : +- AT803X_PAGE_COPPER); +- phy_unlock_mdio_bus(phydev); +- if (ret) +- return ret; +- +- ret = at8031_pll_config(phydev); +- if (ret < 0) +- return ret; +- } +- + /* The RX and TX delay default is: + * after HW reset: RX delay enabled and TX delay disabled + * after SW reset: RX delay enabled, while TX delay retains the +@@ -1604,6 +1585,30 @@ static int at8031_probe(struct phy_devic + AT803X_WOL_EN, 0); + } + ++static int at8031_config_init(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* Some bootloaders leave the fiber page selected. ++ * Switch to the appropriate page (fiber or copper), as otherwise we ++ * read the PHY capabilities from the wrong page. ++ */ ++ phy_lock_mdio_bus(phydev); ++ ret = at803x_write_page(phydev, ++ priv->is_fiber ? AT803X_PAGE_FIBER : ++ AT803X_PAGE_COPPER); ++ phy_unlock_mdio_bus(phydev); ++ if (ret) ++ return ret; ++ ++ ret = at8031_pll_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ return at803x_config_init(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2113,7 +2118,7 @@ static struct phy_driver at803x_driver[] + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, + .probe = at8031_probe, +- .config_init = at803x_config_init, ++ .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, + .set_wol = at803x_set_wol, diff --git a/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch b/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch new file mode 100644 index 0000000000..6746a4d43c --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch @@ -0,0 +1,92 @@ +From 27b89c9dc1b0393090d68d651b82f30ad2696baa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:55 +0100 +Subject: [PATCH 08/13] net: phy: at803x: move specific at8031 WOL bits to + dedicated function + +Move specific at8031 WOL enable/disable to dedicated function to make +at803x_set_wol more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to toggle WOL settings. + +In this new implementation WOL module in at8031 is enabled after the +generic interrupt is setup. This should not cause any problem as the +WOL_INT has a separate implementation and only relay on MAC bits. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 42 ++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -466,27 +466,11 @@ static int at803x_set_wol(struct phy_dev + phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + +- /* Enable WOL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- 0, AT803X_WOL_EN); +- if (ret) +- return ret; +- } + /* Enable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); + if (ret) + return ret; + } else { +- /* Disable WoL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; +- } + /* Disable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); + if (ret) +@@ -1609,6 +1593,30 @@ static int at8031_config_init(struct phy + return at803x_config_init(phydev); + } + ++static int at8031_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret; ++ ++ /* First setup MAC address and enable WOL interrupt */ ++ ret = at803x_set_wol(phydev, wol); ++ if (ret) ++ return ret; ++ ++ if (wol->wolopts & WAKE_MAGIC) ++ /* Enable WOL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ 0, AT803X_WOL_EN); ++ else ++ /* Disable WoL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++ ++ return ret; ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2121,7 +2129,7 @@ static struct phy_driver at803x_driver[] + .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, +- .set_wol = at803x_set_wol, ++ .set_wol = at8031_set_wol, + .get_wol = at803x_get_wol, + .suspend = at803x_suspend, + .resume = at803x_resume, diff --git a/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch b/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch new file mode 100644 index 0000000000..0d284c3d24 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch @@ -0,0 +1,78 @@ +From 30dd62191d3dd97c08f7f9dc9ce77ffab457e4fb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:56 +0100 +Subject: [PATCH 09/13] net: phy: at803x: move specific at8031 config_intr to + dedicated function + +Move specific at8031 config_intr bits to dedicated function to make +at803x_config_initr more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to setup interrupts. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -990,7 +990,6 @@ static int at803x_ack_interrupt(struct p + + static int at803x_config_intr(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int err; + int value; + +@@ -1007,10 +1006,6 @@ static int at803x_config_intr(struct phy + value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; + value |= AT803X_INTR_ENABLE_LINK_FAIL; + value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- if (priv->is_fiber) { +- value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; +- } + + err = phy_write(phydev, AT803X_INTR_ENABLE, value); + } else { +@@ -1617,6 +1612,29 @@ static int at8031_set_wol(struct phy_dev + return ret; + } + ++static int at8031_config_intr(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err, value = 0; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED && ++ priv->is_fiber) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; ++ ++ err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); ++ if (err) ++ return err; ++ } ++ ++ return at803x_config_intr(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2137,7 +2155,7 @@ static struct phy_driver at803x_driver[] + .write_page = at803x_write_page, + .get_features = at803x_get_features, + .read_status = at803x_read_status, +- .config_intr = at803x_config_intr, ++ .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, diff --git a/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch b/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch new file mode 100644 index 0000000000..210949ea81 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch @@ -0,0 +1,78 @@ +From a5ab9d8e7ae0da8328ac1637a9755311508dc8ab Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:57 +0100 +Subject: [PATCH 10/13] net: phy: at803x: make at8031 related DT functions name + more specific + +Rename at8031 related DT function name to a more specific name +referencing they are only related to at8031 and not to the generic +at803x PHY family. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,7 +583,7 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); +@@ -596,7 +596,7 @@ static int at803x_rgmii_reg_set_voltage_ + AT803X_DEBUG_RGMII_1V8, 0); + } + +-static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); + int val; +@@ -610,8 +610,8 @@ static int at803x_rgmii_reg_get_voltage_ + + static const struct regulator_ops vddio_regulator_ops = { + .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at803x_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at803x_rgmii_reg_get_voltage_sel, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, + }; + + static const unsigned int vddio_voltage_table[] = { +@@ -666,7 +666,7 @@ static int at8031_register_regulators(st + return 0; + } + +-static int at803x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) + { + struct phy_device *phydev = upstream; + __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +@@ -710,10 +710,10 @@ static int at803x_sfp_insert(void *upstr + return 0; + } + +-static const struct sfp_upstream_ops at803x_sfp_ops = { ++static const struct sfp_upstream_ops at8031_sfp_ops = { + .attach = phy_sfp_attach, + .detach = phy_sfp_detach, +- .module_insert = at803x_sfp_insert, ++ .module_insert = at8031_sfp_insert, + }; + + static int at803x_parse_dt(struct phy_device *phydev) +@@ -1519,7 +1519,7 @@ static int at8031_parse_dt(struct phy_de + } + + /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- return phy_sfp_probe(phydev, &at803x_sfp_ops); ++ return phy_sfp_probe(phydev, &at8031_sfp_ops); + } + + static int at8031_probe(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch b/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch new file mode 100644 index 0000000000..5856b59751 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch @@ -0,0 +1,297 @@ +From f932a6dc8bae0dae9645b5b1b4c65aed8a8acb2a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:58 +0100 +Subject: [PATCH 11/13] net: phy: at803x: move at8031 functions in dedicated + section + +Move at8031 functions in dedicated section with dedicated at8031 +parse_dt and probe. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 266 +++++++++++++++++++-------------------- + 1 file changed, 133 insertions(+), 133 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,139 +583,6 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, +- unsigned int selector) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- +- if (selector) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_RGMII_1V8); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_RGMII_1V8, 0); +-} +- +-static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- int val; +- +- val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); +- if (val < 0) +- return val; +- +- return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; +-} +- +-static const struct regulator_ops vddio_regulator_ops = { +- .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, +-}; +- +-static const unsigned int vddio_voltage_table[] = { +- 1500000, +- 1800000, +-}; +- +-static const struct regulator_desc vddio_desc = { +- .name = "vddio", +- .of_match = of_match_ptr("vddio-regulator"), +- .n_voltages = ARRAY_SIZE(vddio_voltage_table), +- .volt_table = vddio_voltage_table, +- .ops = &vddio_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static const struct regulator_ops vddh_regulator_ops = { +-}; +- +-static const struct regulator_desc vddh_desc = { +- .name = "vddh", +- .of_match = of_match_ptr("vddh-regulator"), +- .n_voltages = 1, +- .fixed_uV = 2500000, +- .ops = &vddh_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static int at8031_register_regulators(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; +- struct regulator_config config = { }; +- +- config.dev = dev; +- config.driver_data = phydev; +- +- priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); +- if (IS_ERR(priv->vddio_rdev)) { +- phydev_err(phydev, "failed to register VDDIO regulator\n"); +- return PTR_ERR(priv->vddio_rdev); +- } +- +- priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); +- if (IS_ERR(priv->vddh_rdev)) { +- phydev_err(phydev, "failed to register VDDH regulator\n"); +- return PTR_ERR(priv->vddh_rdev); +- } +- +- return 0; +-} +- +-static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) +-{ +- struct phy_device *phydev = upstream; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); +- DECLARE_PHY_INTERFACE_MASK(interfaces); +- phy_interface_t iface; +- +- linkmode_zero(phy_support); +- phylink_set(phy_support, 1000baseX_Full); +- phylink_set(phy_support, 1000baseT_Full); +- phylink_set(phy_support, Autoneg); +- phylink_set(phy_support, Pause); +- phylink_set(phy_support, Asym_Pause); +- +- linkmode_zero(sfp_support); +- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); +- /* Some modules support 10G modes as well as others we support. +- * Mask out non-supported modes so the correct interface is picked. +- */ +- linkmode_and(sfp_support, phy_support, sfp_support); +- +- if (linkmode_empty(sfp_support)) { +- dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); +- return -EINVAL; +- } +- +- iface = sfp_select_interface(phydev->sfp_bus, sfp_support); +- +- /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes +- * interface for use with SFP modules. +- * However, some copper modules detected as having a preferred SGMII +- * interface do default to and function in 1000Base-X mode, so just +- * print a warning and allow such modules, as they may have some chance +- * of working. +- */ +- if (iface == PHY_INTERFACE_MODE_SGMII) +- dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); +- else if (iface != PHY_INTERFACE_MODE_1000BASEX) +- return -EINVAL; +- +- return 0; +-} +- +-static const struct sfp_upstream_ops at8031_sfp_ops = { +- .attach = phy_sfp_attach, +- .detach = phy_sfp_detach, +- .module_insert = at8031_sfp_insert, +-}; +- + static int at803x_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; +@@ -1498,6 +1365,139 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++ unsigned int selector) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ ++ if (selector) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_RGMII_1V8); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_RGMII_1V8, 0); ++} ++ ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ int val; ++ ++ val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); ++ if (val < 0) ++ return val; ++ ++ return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; ++} ++ ++static const struct regulator_ops vddio_regulator_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, ++}; ++ ++static const unsigned int vddio_voltage_table[] = { ++ 1500000, ++ 1800000, ++}; ++ ++static const struct regulator_desc vddio_desc = { ++ .name = "vddio", ++ .of_match = of_match_ptr("vddio-regulator"), ++ .n_voltages = ARRAY_SIZE(vddio_voltage_table), ++ .volt_table = vddio_voltage_table, ++ .ops = &vddio_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct regulator_ops vddh_regulator_ops = { ++}; ++ ++static const struct regulator_desc vddh_desc = { ++ .name = "vddh", ++ .of_match = of_match_ptr("vddh-regulator"), ++ .n_voltages = 1, ++ .fixed_uV = 2500000, ++ .ops = &vddh_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static int at8031_register_regulators(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct regulator_config config = { }; ++ ++ config.dev = dev; ++ config.driver_data = phydev; ++ ++ priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); ++ if (IS_ERR(priv->vddio_rdev)) { ++ phydev_err(phydev, "failed to register VDDIO regulator\n"); ++ return PTR_ERR(priv->vddio_rdev); ++ } ++ ++ priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); ++ if (IS_ERR(priv->vddh_rdev)) { ++ phydev_err(phydev, "failed to register VDDH regulator\n"); ++ return PTR_ERR(priv->vddh_rdev); ++ } ++ ++ return 0; ++} ++ ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ phy_interface_t iface; ++ ++ linkmode_zero(phy_support); ++ phylink_set(phy_support, 1000baseX_Full); ++ phylink_set(phy_support, 1000baseT_Full); ++ phylink_set(phy_support, Autoneg); ++ phylink_set(phy_support, Pause); ++ phylink_set(phy_support, Asym_Pause); ++ ++ linkmode_zero(sfp_support); ++ sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); ++ /* Some modules support 10G modes as well as others we support. ++ * Mask out non-supported modes so the correct interface is picked. ++ */ ++ linkmode_and(sfp_support, phy_support, sfp_support); ++ ++ if (linkmode_empty(sfp_support)) { ++ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ iface = sfp_select_interface(phydev->sfp_bus, sfp_support); ++ ++ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes ++ * interface for use with SFP modules. ++ * However, some copper modules detected as having a preferred SGMII ++ * interface do default to and function in 1000Base-X mode, so just ++ * print a warning and allow such modules, as they may have some chance ++ * of working. ++ */ ++ if (iface == PHY_INTERFACE_MODE_SGMII) ++ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); ++ else if (iface != PHY_INTERFACE_MODE_1000BASEX) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct sfp_upstream_ops at8031_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = at8031_sfp_insert, ++}; ++ + static int at8031_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; diff --git a/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch b/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch new file mode 100644 index 0000000000..0a822c6d37 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch @@ -0,0 +1,114 @@ +From 21a2802a8365cfa82cc02187c1f95136d85592ad Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:59 +0100 +Subject: [PATCH 12/13] net: phy: at803x: move at8035 specific DT parse to + dedicated probe + +Move at8035 specific DT parse for clock out frequency to dedicated probe +to make at803x probe function more generic. + +This is to tidy code and no behaviour change are intended. + +Detection logic is changed, we check if the clk 25m mask is set and if +it's not zero, we assume the qca,clk-out-frequency property is set. + +The property is checked in the generic at803x_parse_dt called by +at803x_probe. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 60 +++++++++++++++++++++++++++------------- + 1 file changed, 41 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -638,23 +638,6 @@ static int at803x_parse_dt(struct phy_de + + priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); + priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; +- +- /* Fixup for the AR8030/AR8035. This chip has another mask and +- * doesn't support the DSP reference. Eg. the lowest bit of the +- * mask. The upper two bits select the same frequencies. Mask +- * the lowest bit here. +- * +- * Warning: +- * There was no datasheet for the AR8030 available so this is +- * just a guess. But the AR8035 is listed as pin compatible +- * to the AR8030 so there might be a good chance it works on +- * the AR8030 too. +- */ +- if (phydev->drv->phy_id == ATH8030_PHY_ID || +- phydev->drv->phy_id == ATH8035_PHY_ID) { +- priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; +- priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; +- } + } + + ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); +@@ -1635,6 +1618,45 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++static int at8035_parse_dt(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* Mask is set by the generic at803x_parse_dt ++ * if property is set. Assume property is set ++ * with the mask not zero. ++ */ ++ if (priv->clk_25m_mask) { ++ /* Fixup for the AR8030/AR8035. This chip has another mask and ++ * doesn't support the DSP reference. Eg. the lowest bit of the ++ * mask. The upper two bits select the same frequencies. Mask ++ * the lowest bit here. ++ * ++ * Warning: ++ * There was no datasheet for the AR8030 available so this is ++ * just a guess. But the AR8035 is listed as pin compatible ++ * to the AR8030 so there might be a good chance it works on ++ * the AR8030 too. ++ */ ++ priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; ++ priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; ++ } ++ ++ return 0; ++} ++ ++/* AR8030 and AR8035 shared the same special mask for clk_25m */ ++static int at8035_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ return at8035_parse_dt(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2107,7 +2129,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), + .name = "Qualcomm Atheros AR8035", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_aneg = at803x_config_aneg, + .config_init = at803x_config_init, + .soft_reset = genphy_soft_reset, +@@ -2128,7 +2150,7 @@ static struct phy_driver at803x_driver[] + .phy_id = ATH8030_PHY_ID, + .name = "Qualcomm Atheros AR8030", + .phy_id_mask = AT8030_PHY_ID_MASK, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_init = at803x_config_init, + .link_change_notify = at803x_link_change_notify, + .set_wol = at803x_set_wol, diff --git a/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch b/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch new file mode 100644 index 0000000000..e1ba6ec2d0 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch @@ -0,0 +1,219 @@ +From ef9df47b449e32e06501a11272809be49019bdb6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:52:00 +0100 +Subject: [PATCH 13/13] net: phy: at803x: drop specific PHY ID check from cable + test functions + +Drop specific PHY ID check for cable test functions for at803x. This is +done to make functions more generic. While at it better describe what +the functions does by using more symbolic function names. + +PHYs that requires to set additional reg are moved to specific function +calling the more generic one. + +cdt_start and cdt_wait_for_completion are changed to take an additional +arg to pass specific values specific to the PHY. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 95 +++++++++++++++++++++------------------- + 1 file changed, 50 insertions(+), 45 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1222,31 +1222,16 @@ static int at803x_cdt_fault_length(u16 s + return (dt * 824) / 10; + } + +-static int at803x_cdt_start(struct phy_device *phydev, int pair) ++static int at803x_cdt_start(struct phy_device *phydev, ++ u32 cdt_start) + { +- u16 cdt; +- +- /* qca8081 takes the different bit 15 to enable CDT test */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; +- else +- cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | +- AT803X_CDT_ENABLE_TEST; +- +- return phy_write(phydev, AT803X_CDT, cdt); ++ return phy_write(phydev, AT803X_CDT, cdt_start); + } + +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev) ++static int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) + { + int val, ret; +- u16 cdt_en; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt_en = QCA808X_CDT_ENABLE_TEST; +- else +- cdt_en = AT803X_CDT_ENABLE_TEST; + + /* One test run takes about 25ms */ + ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +@@ -1266,11 +1251,13 @@ static int at803x_cable_test_one_pair(st + }; + int ret, val; + +- ret = at803x_cdt_start(phydev, pair); ++ val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | ++ AT803X_CDT_ENABLE_TEST; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -1292,19 +1279,11 @@ static int at803x_cable_test_one_pair(st + } + + static int at803x_cable_test_get_status(struct phy_device *phydev, +- bool *finished) ++ bool *finished, unsigned long pair_mask) + { +- unsigned long pair_mask; + int retries = 20; + int pair, ret; + +- if (phydev->phy_id == ATH9331_PHY_ID || +- phydev->phy_id == ATH8032_PHY_ID || +- phydev->phy_id == QCA9561_PHY_ID) +- pair_mask = 0x3; +- else +- pair_mask = 0xf; +- + *finished = false; + + /* According to the datasheet the CDT can be performed when +@@ -1331,7 +1310,7 @@ static int at803x_cable_test_get_status( + return 0; + } + +-static int at803x_cable_test_start(struct phy_device *phydev) ++static void at803x_cable_test_autoneg(struct phy_device *phydev) + { + /* Enable auto-negotiation, but advertise no capabilities, no link + * will be established. A restart of the auto-negotiation is not +@@ -1339,11 +1318,11 @@ static int at803x_cable_test_start(struc + */ + phy_write(phydev, MII_BMCR, BMCR_ANENABLE); + phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); +- if (phydev->phy_id != ATH9331_PHY_ID && +- phydev->phy_id != ATH8032_PHY_ID && +- phydev->phy_id != QCA9561_PHY_ID) +- phy_write(phydev, MII_CTRL1000, 0); ++} + ++static int at803x_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); + /* we do all the (time consuming) work later */ + return 0; + } +@@ -1618,6 +1597,29 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8035 share the same cable test get status reg */ ++static int at8031_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0xf); ++} ++ ++/* AR8031 and AR8035 share the same cable test start logic */ ++static int at8031_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ phy_write(phydev, MII_CTRL1000, 0); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ ++static int at8032_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0x3); ++} ++ + static int at8035_parse_dt(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +@@ -2041,11 +2043,14 @@ static int qca808x_cable_test_get_status + + *finished = false; + +- ret = at803x_cdt_start(phydev, 0); ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT | ++ QCA808X_CDT_INTER_CHECK_DIS; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -2143,8 +2148,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8030 */ + .phy_id = ATH8030_PHY_ID, +@@ -2181,8 +2186,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8032 */ + PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), +@@ -2197,7 +2202,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + }, { + /* ATHEROS AR9331 */ + PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), +@@ -2210,7 +2215,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, +@@ -2226,7 +2231,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, diff --git a/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch b/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch new file mode 100644 index 0000000000..0bb3673c02 --- /dev/null +++ b/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch @@ -0,0 +1,116 @@ +From 8e732f1c6f2dc5e18f766d0f1b11df9db2dd044a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:31 +0100 +Subject: [PATCH 1/2] net: phy: at803x: move specific qca808x config_aneg to + dedicated function + +Move specific qca808x config_aneg to dedicated function to permit easier +split of qca808x portion from at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 66 ++++++++++++++++++++++++---------------- + 1 file changed, 40 insertions(+), 26 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1045,9 +1045,8 @@ static int at803x_config_mdix(struct phy + FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); + } + +-static int at803x_config_aneg(struct phy_device *phydev) ++static int at803x_prepare_config_aneg(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +@@ -1064,33 +1063,22 @@ static int at803x_config_aneg(struct phy + return ret; + } + +- if (priv->is_1000basex) +- return genphy_c37_config_aneg(phydev); +- +- /* Do not restart auto-negotiation by setting ret to 0 defautly, +- * when calling __genphy_config_aneg later. +- */ +- ret = 0; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- int phy_ctrl = 0; ++ return 0; ++} + +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); ++static int at803x_config_aneg(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; + +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; + +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- } ++ if (priv->is_1000basex) ++ return genphy_c37_config_aneg(phydev); + +- return __genphy_config_aneg(phydev, ret); ++ return genphy_config_aneg(phydev); + } + + static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +@@ -2118,6 +2106,32 @@ static int qca808x_get_features(struct p + return 0; + } + ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ + static void qca808x_link_change_notify(struct phy_device *phydev) + { + /* Assert interface sgmii fifo on link down, deassert it on link up, +@@ -2295,7 +2309,7 @@ static struct phy_driver at803x_driver[] + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, + .get_features = qca808x_get_features, +- .config_aneg = at803x_config_aneg, ++ .config_aneg = qca808x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_status = qca808x_read_status, diff --git a/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch b/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch new file mode 100644 index 0000000000..54ca3bdfc8 --- /dev/null +++ b/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch @@ -0,0 +1,97 @@ +From 38eb804e8458ba181a03a0498ce4bf84eebd1931 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:32 +0100 +Subject: [PATCH 2/2] net: phy: at803x: make read specific status function more + generic + +Rework read specific status function to be more generic. The function +apply different speed mask based on the PHY ID. Make it more generic by +adding an additional arg to pass the specific speed (ss) mask and use +the provided mask to parse the speed value. + +This is needed to permit an easier deatch of qca808x code from the +at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -301,6 +301,11 @@ static struct at803x_hw_stat qca83xx_hw_ + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, + }; + ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ + struct at803x_priv { + int flags; + u16 clk_25m_reg; +@@ -921,7 +926,8 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_specific_status(struct phy_device *phydev) ++static int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) + { + int ss; + +@@ -940,11 +946,8 @@ static int at803x_read_specific_status(s + if (sfc < 0) + return sfc; + +- /* qca8081 takes the different bits for speed value from at803x */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss); +- else +- speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss); ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; + + switch (speed) { + case AT803X_SS_SPEED_10: +@@ -989,6 +992,7 @@ static int at803x_read_specific_status(s + static int at803x_read_status(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; ++ struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + + if (priv->is_1000basex) +@@ -1012,7 +1016,9 @@ static int at803x_read_status(struct phy + if (err < 0) + return err; + +- err = at803x_read_specific_status(phydev); ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); + if (err < 0) + return err; + +@@ -1869,6 +1875,7 @@ static int qca808x_config_init(struct ph + + static int qca808x_read_status(struct phy_device *phydev) + { ++ struct at803x_ss_mask ss_mask = { 0 }; + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +@@ -1882,7 +1889,10 @@ static int qca808x_read_status(struct ph + if (ret) + return ret; + +- ret = at803x_read_specific_status(phydev); ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); + if (ret < 0) + return ret; + diff --git a/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch b/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch new file mode 100644 index 0000000000..8097a33e49 --- /dev/null +++ b/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch @@ -0,0 +1,27 @@ +From fc9d7264ddc32eaa647d6bfcdc25cdf9f786fde0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:27:39 +0100 +Subject: [PATCH 1/2] net: phy: at803x: remove extra space after cast + +Remove extra space after cast as reported by checkpatch to keep code +clean. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232739.27065-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -462,7 +462,7 @@ static int at803x_set_wol(struct phy_dev + if (!ndev) + return -ENODEV; + +- mac = (const u8 *) ndev->dev_addr; ++ mac = (const u8 *)ndev->dev_addr; + + if (!is_valid_ether_addr(mac)) + return -EINVAL; diff --git a/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch b/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch new file mode 100644 index 0000000000..b8d4591087 --- /dev/null +++ b/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch @@ -0,0 +1,38 @@ +From 3ab5720881a924fb6405d9e6a3b09f1026467c47 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:25:08 +0100 +Subject: [PATCH 2/2] net: phy: at803x: replace msleep(1) with usleep_range + +Replace msleep(1) with usleep_range as suggested by timers-howto guide. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232508.26470-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -916,9 +916,9 @@ static void at803x_link_change_notify(st + at803x_context_save(phydev, &context); + + phy_device_reset(phydev, 1); +- msleep(1); ++ usleep_range(1000, 2000); + phy_device_reset(phydev, 0); +- msleep(1); ++ usleep_range(1000, 2000); + + at803x_context_restore(phydev, &context); + +@@ -1733,7 +1733,7 @@ static int qca83xx_resume(struct phy_dev + if (ret) + return ret; + +- msleep(1); ++ usleep_range(1000, 2000); + + return 0; + } diff --git a/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch b/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch new file mode 100644 index 0000000000..776b7bb43f --- /dev/null +++ b/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch @@ -0,0 +1,152 @@ +From 7961ef1fa10ec35ad6923fb5751877116e4b035b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 19 Dec 2023 21:21:24 +0100 +Subject: [PATCH] net: phy: at803x: better align function varibles to open + parenthesis + +Better align function variables to open parenthesis as suggested by +checkpatch script for qca808x function to make code cleaner. + +For cable_test_get_status function some additional rework was needed to +handle too long functions. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 67 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 30 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1781,27 +1781,27 @@ static int qca808x_phy_fast_retrain_conf + return ret; + + phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); ++ QCA808X_TOP_OPTION1_DATA); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); ++ QCA808X_MMD3_DEBUG_1_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); ++ QCA808X_MMD3_DEBUG_4_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); ++ QCA808X_MMD3_DEBUG_5_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); ++ QCA808X_MMD3_DEBUG_3_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); ++ QCA808X_MMD3_DEBUG_6_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); ++ QCA808X_MMD3_DEBUG_2_VALUE); + + return 0; + } +@@ -1838,13 +1838,14 @@ static int qca808x_config_init(struct ph + + /* Active adc&vga on 802.3az for the link 1000M and 100M */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); + if (ret) + return ret; + + /* Adjust the threshold on 802.3az for the link 1000M */ + ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, QCA808X_MMD3_AZ_TRAINING_VAL); ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); + if (ret) + return ret; + +@@ -1870,7 +1871,8 @@ static int qca808x_config_init(struct ph + + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); + } + + static int qca808x_read_status(struct phy_device *phydev) +@@ -1883,7 +1885,7 @@ static int qca808x_read_status(struct ph + return ret; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); + + ret = genphy_read_status(phydev); + if (ret) +@@ -1913,7 +1915,7 @@ static int qca808x_read_status(struct ph + */ + if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); +@@ -2070,18 +2072,22 @@ static int qca808x_cable_test_get_status + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, + qca808x_cable_test_result_trans(pair_d)); + +- if (qca808x_cdt_fault_length_valid(pair_a)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A)); +- if (qca808x_cdt_fault_length_valid(pair_b)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B)); +- if (qca808x_cdt_fault_length_valid(pair_c)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C)); +- if (qca808x_cdt_fault_length_valid(pair_d)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D)); ++ if (qca808x_cdt_fault_length_valid(pair_a)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_b)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_c)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_d)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ } + + *finished = true; + +@@ -2148,8 +2154,9 @@ static void qca808x_link_change_notify(s + * the interface device address is always phy address added by 1. + */ + mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); + } + + static struct phy_driver at803x_driver[] = { diff --git a/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch b/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch new file mode 100644 index 0000000000..d7196da46e --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch @@ -0,0 +1,62 @@ +From 22eb276098da820d9440fad22901f9b74ed4d659 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:38 +0100 +Subject: [PATCH 1/4] net: phy: at803x: generalize cdt fault length function + +Generalize cable test fault length function since they all base on the +same magic values (already reverse engineered to understand the meaning +of it) to have consistenct values on every PHY. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1192,10 +1192,8 @@ static bool at803x_cdt_fault_length_vali + return false; + } + +-static int at803x_cdt_fault_length(u16 status) ++static int at803x_cdt_fault_length(int dt) + { +- int dt; +- + /* According to the datasheet the distance to the fault is + * DELTA_TIME * 0.824 meters. + * +@@ -1211,8 +1209,6 @@ static int at803x_cdt_fault_length(u16 s + * With a VF of 0.69 we get the factor 0.824 mentioned in the + * datasheet. + */ +- dt = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, status); +- + return (dt * 824) / 10; + } + +@@ -1265,9 +1261,11 @@ static int at803x_cable_test_one_pair(st + ethnl_cable_test_result(phydev, ethtool_pair[pair], + at803x_cable_test_result_trans(val)); + +- if (at803x_cdt_fault_length_valid(val)) ++ if (at803x_cdt_fault_length_valid(val)) { ++ val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); + ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], + at803x_cdt_fault_length(val)); ++ } + + return 1; + } +@@ -1992,7 +1990,8 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- return (FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val) * 824) / 10; ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ return at803x_cdt_fault_length(val); + } + + static int qca808x_cable_test_start(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch b/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch new file mode 100644 index 0000000000..5d38fe7e91 --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch @@ -0,0 +1,118 @@ +From e0e9ada1df6133513249861c1d91c1dbefd9383b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:39 +0100 +Subject: [PATCH 2/4] net: phy: at803x: refactor qca808x cable test get status + function + +Refactor qca808x cable test get status function to remove code +duplication and clean things up. + +The same logic is applied to each pair hence it can be generalized and +moved to a common function. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 80 ++++++++++++++++++++++++---------------- + 1 file changed, 49 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -2035,10 +2035,43 @@ static int qca808x_cable_test_start(stru + return 0; + } + ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ u16 pair_code; ++ int length; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ethnl_cable_test_result(phydev, pair, ++ qca808x_cable_test_result_trans(pair_code)); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ + static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) + { + int ret, val; +- int pair_a, pair_b, pair_c, pair_d; + + *finished = false; + +@@ -2057,36 +2090,21 @@ static int qca808x_cable_test_get_status + if (val < 0) + return val; + +- pair_a = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, val); +- pair_b = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, val); +- pair_c = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, val); +- pair_d = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, val); +- +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cable_test_result_trans(pair_a)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cable_test_result_trans(pair_b)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cable_test_result_trans(pair_c)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cable_test_result_trans(pair_d)); +- +- if (qca808x_cdt_fault_length_valid(pair_a)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_b)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_c)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_d)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- } ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; + + *finished = true; + diff --git a/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch b/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch new file mode 100644 index 0000000000..d5793860a9 --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch @@ -0,0 +1,182 @@ +From ea73e5ea442ee2aade67b1fb1233ccb3cbea2ceb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:40 +0100 +Subject: [PATCH 3/4] net: phy: at803x: add support for cdt cross short test + for qca808x + +QCA808x PHY Family supports Cable Diagnostic Test also for Cross Pair +Short. + +Add all the define to make enable and support these additional tests. + +Cross Short test was previously disabled by default, this is now changed +and enabled by default. In this mode, the mask changed a bit and length +is shifted based on the fault condition. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 86 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 69 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -254,6 +254,7 @@ + + #define QCA808X_CDT_ENABLE_TEST BIT(15) + #define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) + #define QCA808X_CDT_LENGTH_UNIT BIT(10) + + #define QCA808X_MMD3_CDT_STATUS 0x8064 +@@ -261,16 +262,44 @@ + #define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 + #define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 + #define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH GENMASK(7, 0) ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) + + #define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) + #define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) + #define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) + #define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL 0 +-#define QCA808X_CDT_STATUS_STAT_NORMAL 1 +-#define QCA808X_CDT_STATUS_STAT_OPEN 2 +-#define QCA808X_CDT_STATUS_STAT_SHORT 3 ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + + /* QCA808X 1G chip type */ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +@@ -1941,8 +1970,17 @@ static int qca808x_soft_reset(struct phy + static bool qca808x_cdt_fault_length_valid(int cdt_code) + { + switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SHORT: +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: + return true; + default: + return false; +@@ -1954,17 +1992,28 @@ static int qca808x_cable_test_result_tra + switch (cdt_code) { + case QCA808X_CDT_STATUS_STAT_NORMAL: + return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; + case QCA808X_CDT_STATUS_STAT_FAIL: + default: + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; + } + } + +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair) ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) + { + int val; + u32 cdt_length_reg = 0; +@@ -1990,7 +2039,11 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ + return at803x_cdt_fault_length(val); + } + +@@ -2038,8 +2091,8 @@ static int qca808x_cable_test_start(stru + static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, + u16 status) + { ++ int length, result; + u16 pair_code; +- int length; + + switch (pair) { + case ETHTOOL_A_CABLE_PAIR_A: +@@ -2058,11 +2111,11 @@ static int qca808x_cable_test_get_pair_s + return -EINVAL; + } + +- ethnl_cable_test_result(phydev, pair, +- qca808x_cable_test_result_trans(pair_code)); ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); + + if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair); ++ length = qca808x_cdt_fault_length(phydev, pair, result); + ethnl_cable_test_fault_length(phydev, pair, length); + } + +@@ -2076,8 +2129,7 @@ static int qca808x_cable_test_get_status + *finished = false; + + val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; ++ QCA808X_CDT_LENGTH_UNIT; + ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; diff --git a/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch b/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch new file mode 100644 index 0000000000..c146e502fe --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch @@ -0,0 +1,62 @@ +From c34d9452d4e5d98a655d7b625e85466320885416 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:41 +0100 +Subject: [PATCH 4/4] net: phy: at803x: make read_status more generic + +Make read_status more generic in preparation on moving it to shared +library as other PHY Family Driver will have the exact same +implementation. + +The only specific part was a check for AR8031/33 if 1000basex was used. +The check is moved to a dedicated function specific for those PHYs. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1020,13 +1020,9 @@ static int at803x_read_specific_status(s + + static int at803x_read_status(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + +- if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); +- + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) +@@ -1618,6 +1614,17 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8033 share the same read status logic */ ++static int at8031_read_status(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_read_status(phydev); ++ ++ return at803x_read_status(phydev); ++} ++ + /* AR8031 and AR8035 share the same cable test get status reg */ + static int at8031_cable_test_get_status(struct phy_device *phydev, + bool *finished) +@@ -2281,7 +2288,7 @@ static struct phy_driver at803x_driver[] + .read_page = at803x_read_page, + .write_page = at803x_write_page, + .get_features = at803x_get_features, +- .read_status = at803x_read_status, ++ .read_status = at8031_read_status, + .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, diff --git a/target/linux/generic/backport-6.1/707-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch b/target/linux/generic/backport-6.1/723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch similarity index 99% rename from target/linux/generic/backport-6.1/707-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch rename to target/linux/generic/backport-6.1/723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch index 980cb0f914..d56a142451 100644 --- a/target/linux/generic/backport-6.1/707-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch +++ b/target/linux/generic/backport-6.1/723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12926,6 +12926,14 @@ L: netdev@vger.kernel.org +@@ -12928,6 +12928,14 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/mediatek/ diff --git a/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch b/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch similarity index 62% rename from target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch rename to target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch index 35c0d850cd..789b93e9f9 100644 --- a/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch +++ b/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch @@ -1,7 +1,7 @@ -From b5532bdc6d09e6e789417f0c7a0b665b57b0e7be Mon Sep 17 00:00:00 2001 +From 7f3eb2174512fe6c9c0f062e96eccb0d3cc6d5cd Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Mon, 18 Sep 2023 14:21:56 +0200 -Subject: [PATCH 1/4] net: introduce napi_is_scheduled helper +Date: Wed, 18 Oct 2023 14:35:47 +0200 +Subject: [PATCH] net: introduce napi_is_scheduled helper We currently have napi_if_scheduled_mark_missed that can be used to check if napi is scheduled but that does more thing than simply checking @@ -15,12 +15,13 @@ Update any driver and code that implement a similar check and instead use this new helper. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- - drivers/net/ethernet/chelsio/cxgb3/sge.c | 8 -------- - drivers/net/wireless/realtek/rtw89/core.c | 2 +- - include/linux/netdevice.h | 5 +++++ - net/core/dev.c | 2 +- - 4 files changed, 7 insertions(+), 10 deletions(-) + drivers/net/ethernet/chelsio/cxgb3/sge.c | 8 -------- + drivers/net/wireless/realtek/rtw89/core.c | 2 +- + include/linux/netdevice.h | 23 +++++++++++++++++++++++ + net/core/dev.c | 2 +- + 4 files changed, 25 insertions(+), 10 deletions(-) --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -52,10 +53,28 @@ Signed-off-by: Christian Marangi rtw89_core_hw_to_sband_rate(rx_status); --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -468,6 +468,11 @@ static inline bool napi_prefer_busy_poll +@@ -468,6 +468,29 @@ static inline bool napi_prefer_busy_poll return test_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state); } ++/** ++ * napi_is_scheduled - test if NAPI is scheduled ++ * @n: NAPI context ++ * ++ * This check is "best-effort". With no locking implemented, ++ * a NAPI can be scheduled or terminate right after this check ++ * and produce not precise results. ++ * ++ * NAPI_STATE_SCHED is an internal state, napi_is_scheduled ++ * should not be used normally and napi_schedule should be ++ * used instead. ++ * ++ * Use only if the driver really needs to check if a NAPI ++ * is scheduled for example in the context of delayed timer ++ * that can be skipped if a NAPI is already scheduled. ++ * ++ * Return True if NAPI is scheduled, False otherwise. ++ */ +static inline bool napi_is_scheduled(struct napi_struct *n) +{ + return test_bit(NAPI_STATE_SCHED, &n->state); @@ -66,7 +85,7 @@ Signed-off-by: Christian Marangi /** --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6591,7 +6591,7 @@ static int __napi_poll(struct napi_struc +@@ -6533,7 +6533,7 @@ static int __napi_poll(struct napi_struc * accidentally calling ->poll() when NAPI is not scheduled. */ work = 0; diff --git a/target/linux/ipq806x/patches-6.1/700-03-net-stmmac-improve-TX-timer-arm-logic.patch b/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch similarity index 91% rename from target/linux/ipq806x/patches-6.1/700-03-net-stmmac-improve-TX-timer-arm-logic.patch rename to target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch index 21c7ff1777..07c087260c 100644 --- a/target/linux/ipq806x/patches-6.1/700-03-net-stmmac-improve-TX-timer-arm-logic.patch +++ b/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch @@ -1,7 +1,7 @@ -From cd40cd8b1ca4a6f531c6c3fd78b306e5014f9c04 Mon Sep 17 00:00:00 2001 +From 2d1a42cf7f77cda54dbbee18d00b1200e7bc22aa Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Mon, 18 Sep 2023 14:39:01 +0200 -Subject: [PATCH 3/4] net: stmmac: improve TX timer arm logic +Date: Wed, 18 Oct 2023 14:35:48 +0200 +Subject: [PATCH 1/3] net: stmmac: improve TX timer arm logic There is currently a problem with the TX timer getting armed multiple unnecessary times causing big performance regression on some device that @@ -39,13 +39,14 @@ With the following new logic the original performance are restored while keeping using the hrtimer. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2976,13 +2976,25 @@ static void stmmac_tx_timer_arm(struct s +@@ -2975,13 +2975,25 @@ static void stmmac_tx_timer_arm(struct s { struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; u32 tx_coal_timer = priv->tx_coal_timer[queue]; diff --git a/target/linux/ipq806x/patches-6.1/700-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch b/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch similarity index 71% rename from target/linux/ipq806x/patches-6.1/700-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch rename to target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch index 6df071c9b8..d1e04e9069 100644 --- a/target/linux/ipq806x/patches-6.1/700-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch +++ b/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch @@ -1,7 +1,7 @@ -From fb04db35447d1e8ff557c8e57139164cecab7de5 Mon Sep 17 00:00:00 2001 +From a594166387fe08e6f5a32130c400249a35b298f9 Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Wed, 27 Sep 2023 15:38:31 +0200 -Subject: [PATCH 2/4] net: stmmac: move TX timer arm after DMA enable +Date: Wed, 18 Oct 2023 14:35:49 +0200 +Subject: [PATCH 2/3] net: stmmac: move TX timer arm after DMA enable Move TX timer arm call after DMA interrupt is enabled again. @@ -11,15 +11,21 @@ we permit to correctly skip if a DMA interrupt has been fired and a napi has been scheduled again. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 19 +++++++++++++++---- - 1 file changed, 15 insertions(+), 4 deletions(-) + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 22 +++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2530,7 +2530,8 @@ static void stmmac_bump_dma_threshold(st +@@ -2528,9 +2528,13 @@ static void stmmac_bump_dma_threshold(st + * @priv: driver private structure + * @budget: napi budget limiting this functions packet handling * @queue: TX queue index ++ * @pending_packets: signal to arm the TX coal timer * Description: it reclaims the transmit resources after transmission completes. ++ * If some packets still needs to be handled, due to TX coalesce, set ++ * pending_packets to true to make NAPI arm the TX coal timer. */ -static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) +static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, @@ -27,7 +33,7 @@ Signed-off-by: Christian Marangi { struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; unsigned int bytes_compl = 0, pkts_compl = 0; -@@ -2693,7 +2694,7 @@ static int stmmac_tx_clean(struct stmmac +@@ -2693,7 +2697,7 @@ static int stmmac_tx_clean(struct stmmac /* We still have pending packets, let's call for a new scheduling */ if (tx_q->dirty_tx != tx_q->cur_tx) @@ -36,7 +42,7 @@ Signed-off-by: Christian Marangi __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); -@@ -5473,12 +5474,13 @@ static int stmmac_napi_poll_tx(struct na +@@ -5485,12 +5489,13 @@ static int stmmac_napi_poll_tx(struct na struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, tx_napi); struct stmmac_priv *priv = ch->priv_data; @@ -51,7 +57,7 @@ Signed-off-by: Christian Marangi work_done = min(work_done, budget); if (work_done < budget && napi_complete_done(napi, work_done)) { -@@ -5489,6 +5491,10 @@ static int stmmac_napi_poll_tx(struct na +@@ -5501,6 +5506,10 @@ static int stmmac_napi_poll_tx(struct na spin_unlock_irqrestore(&ch->lock, flags); } @@ -62,11 +68,12 @@ Signed-off-by: Christian Marangi return work_done; } -@@ -5498,11 +5504,12 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5509,12 +5518,13 @@ static int stmmac_napi_poll_rxtx(struct + struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, rxtx_napi); struct stmmac_priv *priv = ch->priv_data; - int rx_done, tx_done, rxtx_done; + bool tx_pending_packets = false; + int rx_done, tx_done, rxtx_done; u32 chan = ch->index; priv->xstats.napi_poll++; @@ -76,7 +83,7 @@ Signed-off-by: Christian Marangi tx_done = min(tx_done, budget); rx_done = stmmac_rx_zc(priv, budget, chan); -@@ -5527,6 +5534,10 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5539,6 +5549,10 @@ static int stmmac_napi_poll_rxtx(struct spin_unlock_irqrestore(&ch->lock, flags); } diff --git a/target/linux/ipq806x/patches-6.1/700-04-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch b/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch similarity index 86% rename from target/linux/ipq806x/patches-6.1/700-04-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch rename to target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch index 3f97702097..cc8cbf5a16 100644 --- a/target/linux/ipq806x/patches-6.1/700-04-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch +++ b/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch @@ -1,7 +1,7 @@ -From 95281ab33fbaa1e974bceb20cfb0f5c92934f2b3 Mon Sep 17 00:00:00 2001 +From 039550960a2235cfe2dfaa773df9f98f8da31a0c Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Mon, 18 Sep 2023 15:11:13 +0200 -Subject: [PATCH 4/4] net: stmmac: increase TX coalesce timer to 5ms +Date: Wed, 18 Oct 2023 14:35:50 +0200 +Subject: [PATCH 3/3] net: stmmac: increase TX coalesce timer to 5ms Commit 8fce33317023 ("net: stmmac: Rework coalesce timer and fix multi-queue races") decreased the TX coalesce timer from 40ms to 1ms. @@ -20,6 +20,7 @@ much interrupt to be generated and permitting good performance for internet oriented devices. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch index b75710ba57..d203711884 100644 --- a/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch +++ b/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch @@ -25,7 +25,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13060,6 +13060,7 @@ M: Landen Chao L: netdev@vger.kernel.org S: Maintained diff --git a/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch index 934af995cd..63bf0e77fa 100644 --- a/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch +++ b/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch @@ -28,7 +28,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13058,9 +13058,11 @@ MEDIATEK SWITCH DRIVER +@@ -13060,9 +13060,11 @@ MEDIATEK SWITCH DRIVER M: Sean Wang M: Landen Chao M: DENG Qingfang diff --git a/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch index 06dddffcaa..4cdd67cdcc 100644 --- a/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ b/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch @@ -21,7 +21,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13962,6 +13962,7 @@ F: include/uapi/linux/meye.h +@@ -13964,6 +13964,7 @@ F: include/uapi/linux/meye.h MOTORCOMM PHY DRIVER M: Peter Geis diff --git a/target/linux/generic/backport-6.1/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch b/target/linux/generic/backport-6.1/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch new file mode 100644 index 0000000000..010ca9b68a --- /dev/null +++ b/target/linux/generic/backport-6.1/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch @@ -0,0 +1,170 @@ +From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Thu, 20 Jul 2023 19:15:09 +0800 +Subject: [PATCH] net: phy: motorcomm: Add pad drive strength cfg support + +The motorcomm phy (YT8531) supports the ability to adjust the drive +strength of the rx_clk/rx_data, and the default strength may not be +suitable for all boards. So add configurable options to better match +the boards.(e.g. StarFive VisionFive 2) + +When we configure the drive strength, we need to read the current +LDO voltage value to ensure that it is a legal value at that LDO +voltage. + +Reviewed-by: Hal Feng +Signed-off-by: Samin Guo +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 118 insertions(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -163,6 +163,10 @@ + + #define YT8521_CHIP_CONFIG_REG 0xA001 + #define YT8521_CCR_SW_RST BIT(15) ++#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) ++#define YT8531_LDO_VOL_3V3 0x0 ++#define YT8531_LDO_VOL_1V8 0x2 ++ + /* 1b0 disable 1.9ns rxc clock delay *default* + * 1b1 enable 1.9ns rxc clock delay + */ +@@ -236,6 +240,12 @@ + */ + #define YTPHY_WCR_TYPE_PULSE BIT(0) + ++#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 ++#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) ++#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ ++#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ ++#define YT8531_RGMII_RX_DS_DEFAULT 0x3 ++ + #define YTPHY_SYNCE_CFG_REG 0xA012 + #define YT8521_SCR_SYNCE_ENABLE BIT(5) + /* 1b0 output 25m clock +@@ -835,6 +845,110 @@ static int ytphy_rgmii_clk_delay_config_ + } + + /** ++ * struct ytphy_ldo_vol_map - map a current value to a register value ++ * @vol: ldo voltage ++ * @ds: value in the register ++ * @cur: value in device configuration ++ */ ++struct ytphy_ldo_vol_map { ++ u32 vol; ++ u32 ds; ++ u32 cur; ++}; ++ ++static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, ++}; ++ ++static u32 yt8531_get_ldo_vol(struct phy_device *phydev) ++{ ++ u32 val; ++ ++ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); ++ val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); ++ ++ return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; ++} ++ ++static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) ++{ ++ u32 vol; ++ int i; ++ ++ vol = yt8531_get_ldo_vol(phydev); ++ for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { ++ if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) ++ return yt8531_ldo_vol[i].ds; ++ } ++ ++ return -EINVAL; ++} ++ ++static int yt8531_set_ds(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ u32 ds_field_low, ds_field_hi, val; ++ int ret, ds; ++ ++ /* set rgmii rx clk driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXC_DS_MASK, ++ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); ++ if (ret < 0) ++ return ret; ++ ++ /* set rgmii rx data driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ds_field_hi = FIELD_GET(BIT(2), ds); ++ ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); ++ ++ ds_field_low = FIELD_GET(GENMASK(1, 0), ds); ++ ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, ++ ds_field_low | ds_field_hi); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/** + * yt8521_probe() - read chip config then set suitable polling_mode + * @phydev: a pointer to a &struct phy_device + * +@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy + return ret; + } + ++ ret = yt8531_set_ds(phydev); ++ if (ret < 0) ++ return ret; ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch index eac8966a48..893a81246d 100644 --- a/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch +++ b/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller bool mac_link_dropped; bool using_mac_select_pcs; -@@ -987,6 +992,22 @@ static void phylink_mac_pcs_an_restart(s +@@ -990,6 +995,22 @@ static void phylink_mac_pcs_an_restart(s } } @@ -58,7 +58,7 @@ Signed-off-by: David S. Miller static void phylink_major_config(struct phylink *pl, bool restart, const struct phylink_link_state *state) { -@@ -1023,11 +1044,16 @@ static void phylink_major_config(struct +@@ -1026,11 +1047,16 @@ static void phylink_major_config(struct /* If we have a new PCS, switch to the new PCS after preparing the MAC * for the change. */ @@ -76,7 +76,7 @@ Signed-off-by: David S. Miller if (pl->pcs) { err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, state->interface, -@@ -1499,6 +1525,7 @@ struct phylink *phylink_create(struct ph +@@ -1502,6 +1528,7 @@ struct phylink *phylink_create(struct ph pl->link_config.speed = SPEED_UNKNOWN; pl->link_config.duplex = DUPLEX_UNKNOWN; pl->link_config.an_enabled = true; @@ -84,7 +84,7 @@ Signed-off-by: David S. Miller pl->mac_ops = mac_ops; __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -1900,6 +1927,8 @@ void phylink_start(struct phylink *pl) +@@ -1903,6 +1930,8 @@ void phylink_start(struct phylink *pl) if (pl->netdev) netif_carrier_off(pl->netdev); @@ -93,7 +93,7 @@ Signed-off-by: David S. Miller /* Apply the link configuration to the MAC when starting. This allows * a fixed-link to start with the correct parameters, and also * ensures that we set the appropriate advertisement for Serdes links. -@@ -1910,6 +1939,8 @@ void phylink_start(struct phylink *pl) +@@ -1913,6 +1942,8 @@ void phylink_start(struct phylink *pl) */ phylink_mac_initial_config(pl, true); @@ -102,7 +102,7 @@ Signed-off-by: David S. Miller phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { -@@ -1928,15 +1959,9 @@ void phylink_start(struct phylink *pl) +@@ -1931,15 +1962,9 @@ void phylink_start(struct phylink *pl) poll = true; } @@ -120,7 +120,7 @@ Signed-off-by: David S. Miller if (poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) -@@ -1973,6 +1998,10 @@ void phylink_stop(struct phylink *pl) +@@ -1976,6 +2001,10 @@ void phylink_stop(struct phylink *pl) } phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); diff --git a/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch b/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch index a9e3c71d54..c4141eee93 100644 --- a/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch +++ b/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch @@ -46,7 +46,7 @@ Signed-off-by: David S. Miller --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1668,7 +1668,6 @@ struct net_device_ops { +@@ -1691,7 +1691,6 @@ struct net_device_ops { * @IFF_FAILOVER: device is a failover master device * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device @@ -54,7 +54,7 @@ Signed-off-by: David S. Miller * @IFF_TX_SKB_NO_LINEAR: device/driver is capable of xmitting frames with * skb_headlen(skb) == 0 (data starts from frag0) * @IFF_CHANGE_PROTO_DOWN: device supports setting carrier via IFLA_PROTO_DOWN -@@ -1704,7 +1703,7 @@ enum netdev_priv_flags { +@@ -1727,7 +1726,7 @@ enum netdev_priv_flags { IFF_FAILOVER = 1<<27, IFF_FAILOVER_SLAVE = 1<<28, IFF_L3MDEV_RX_HANDLER = 1<<29, @@ -63,7 +63,7 @@ Signed-off-by: David S. Miller IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), }; -@@ -1739,7 +1738,6 @@ enum netdev_priv_flags { +@@ -1762,7 +1761,6 @@ enum netdev_priv_flags { #define IFF_FAILOVER IFF_FAILOVER #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER diff --git a/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch index a3184513ee..d33fc72dd1 100644 --- a/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch +++ b/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch @@ -153,7 +153,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -593,6 +594,7 @@ struct macsec_ops; +@@ -602,6 +603,7 @@ struct macsec_ops; * @phy_num_led_triggers: Number of triggers in @phy_led_triggers * @led_link_trigger: LED trigger for link up/down * @last_triggered: last LED trigger for link speed @@ -161,7 +161,7 @@ Signed-off-by: David S. Miller * @master_slave_set: User requested master/slave configuration * @master_slave_get: Current master/slave advertisement * @master_slave_state: Current master/slave configuration -@@ -685,6 +687,7 @@ struct phy_device { +@@ -694,6 +696,7 @@ struct phy_device { struct phy_led_trigger *led_link_trigger; #endif @@ -169,7 +169,7 @@ Signed-off-by: David S. Miller /* * Interrupt number for this PHY -@@ -759,6 +762,19 @@ struct phy_tdr_config { +@@ -768,6 +771,19 @@ struct phy_tdr_config { #define PHY_PAIR_ALL -1 /** diff --git a/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 57db12ed4a..c1678ce2ea 100644 --- a/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -59,7 +59,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -765,15 +765,19 @@ struct phy_tdr_config { +@@ -774,15 +774,19 @@ struct phy_tdr_config { * struct phy_led: An LED driven by the PHY * * @list: List of LEDs @@ -79,7 +79,7 @@ Signed-off-by: David S. Miller /** * struct phy_driver - Driver structure for a particular PHY type * -@@ -988,6 +992,15 @@ struct phy_driver { +@@ -997,6 +1001,15 @@ struct phy_driver { int (*get_sqi)(struct phy_device *dev); /** @get_sqi_max: Get the maximum signal quality indication */ int (*get_sqi_max)(struct phy_device *dev); diff --git a/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index e868722afa..f234b2bff1 100644 --- a/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -52,7 +52,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1001,6 +1001,18 @@ struct phy_driver { +@@ -1010,6 +1010,18 @@ struct phy_driver { */ int (*led_brightness_set)(struct phy_device *dev, u8 index, enum led_brightness value); diff --git a/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch b/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch new file mode 100644 index 0000000000..1bf3ba35b6 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch @@ -0,0 +1,94 @@ +From 401df0d4f4098ecc9c5278da2f50756d62e5b37d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:03 +0100 +Subject: [PATCH] nvmem: layouts: refactor .add_cells() callback arguments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simply pass whole "struct nvmem_layout" instead of single variables. +There is nothing in "struct nvmem_layout" that we have to hide from +layout drivers. They also access it during .probe() and .remove(). + +Thanks to this change: + +1. API gets more consistent + All layouts drivers callbacks get the same argument + +2. Layouts get correct device + Before this change NVMEM core code was passing NVMEM device instead + of layout device. That resulted in: + * Confusing prints + * Calling devm_*() helpers on wrong device + * Helpers like of_device_get_match_data() dereferencing NULLs + +3. It gets possible to get match data + First of all nvmem_layout_get_match_data() requires passing "struct + nvmem_layout" which .add_cells() callback didn't have before this. It + doesn't matter much as it's rather useless now anyway (and will be + dropped). + What's more important however is that of_device_get_match_data() can + be used now thanks to owning a proper device pointer. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 4 +++- + drivers/nvmem/layouts/sl28vpd.c | 4 +++- + include/linux/nvmem-provider.h | 2 +- + 4 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -855,7 +855,7 @@ int nvmem_layout_register(struct nvmem_l + return -EINVAL; + + /* Populate the cells */ +- ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(layout); + if (ret) + return ret; + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,10 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) ++static int onie_tlv_parse_table(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; + u8 *table, *data; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,10 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) ++static int sl28vpd_add_cells(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; + struct device_node *layout_np; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -173,7 +173,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + struct device dev; + struct nvmem_device *nvmem; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++ int (*add_cells)(struct nvmem_layout *layout); + }; + + struct nvmem_layout_driver { diff --git a/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch b/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch new file mode 100644 index 0000000000..514b5f2de5 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch @@ -0,0 +1,72 @@ +From 43f60e3fb62edc7bd8891de8779fb422f4ae23ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:04 +0100 +Subject: [PATCH] nvmem: drop nvmem_layout_get_match_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Thanks for layouts refactoring we now have "struct device" associated +with layout. Also its OF pointer points directly to the "nvmem-layout" +DT node. + +All it takes to get match data is a generic of_device_get_match_data(). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 ------------- + include/linux/nvmem-provider.h | 10 ---------- + 2 files changed, 23 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -877,19 +877,6 @@ void nvmem_layout_unregister(struct nvme + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- struct device_node __maybe_unused *layout_np; +- const struct of_device_id *match; +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->dev.driver->of_match_table, layout_np); +- +- return match ? match->data : NULL; +-} +-EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); +- + /** + * nvmem_register() - Register a nvmem device for given nvmem_config. + * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -205,9 +205,6 @@ void nvmem_layout_driver_unregister(stru + module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ + nvmem_layout_driver_unregister) + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout); +- + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -238,13 +235,6 @@ static inline int nvmem_layout_register( + + static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} + +-static inline const void * +-nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- return NULL; +-} +- + #endif /* CONFIG_NVMEM */ + + #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) diff --git a/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch b/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch new file mode 100644 index 0000000000..aa0bbaa0c5 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch @@ -0,0 +1,53 @@ +From 33cf42e68efc8ff529a7eee08a4f0ba8c8d0a207 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:17 +0100 +Subject: [PATCH] nvmem: core: add nvmem_dev_size() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is required by layouts that need to read whole NVMEM content. It's +especially useful for NVMEM devices without hardcoded layout (like +U-Boot environment data block). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 +++++++++++++ + include/linux/nvmem-consumer.h | 1 + + 2 files changed, 14 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -2164,6 +2164,19 @@ const char *nvmem_dev_name(struct nvmem_ + } + EXPORT_SYMBOL_GPL(nvmem_dev_name); + ++/** ++ * nvmem_dev_size() - Get the size of a given nvmem device. ++ * ++ * @nvmem: nvmem device. ++ * ++ * Return: size of the nvmem device. ++ */ ++size_t nvmem_dev_size(struct nvmem_device *nvmem) ++{ ++ return nvmem->size; ++} ++EXPORT_SYMBOL_GPL(nvmem_dev_size); ++ + static int __init nvmem_init(void) + { + int ret; +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -81,6 +81,7 @@ int nvmem_device_cell_write(struct nvmem + struct nvmem_cell_info *info, void *buf); + + const char *nvmem_dev_name(struct nvmem_device *nvmem); ++size_t nvmem_dev_size(struct nvmem_device *nvmem); + + void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, + size_t nentries); diff --git a/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch b/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch new file mode 100644 index 0000000000..fc826f3f7e --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch @@ -0,0 +1,126 @@ +From 7c8979b42b1a9c5604f431ba804928e55919263c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:18 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem_add_one_cell() nvmem subsystem + helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplify adding NVMEM cells. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-3-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 55 +++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 34 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -23,13 +23,10 @@ enum u_boot_env_format { + + struct u_boot_env { + struct device *dev; ++ struct nvmem_device *nvmem; + enum u_boot_env_format format; + + struct mtd_info *mtd; +- +- /* Cells */ +- struct nvmem_cell_info *cells; +- int ncells; + }; + + struct u_boot_env_image_single { +@@ -94,43 +91,36 @@ static int u_boot_env_read_post_process_ + static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + char *data = buf + data_offset; + char *var, *value, *eq; +- int idx; +- +- priv->ncells = 0; +- for (var = data; var < data + data_len && *var; var += strlen(var) + 1) +- priv->ncells++; +- +- priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; + +- for (var = data, idx = 0; ++ for (var = data; + var < data + data_len && *var; +- var = value + strlen(value) + 1, idx++) { ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) + return -ENOMEM; +- priv->cells[idx].offset = data_offset + value - data; +- priv->cells[idx].bytes = strlen(value); +- priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); + if (!strcmp(var, "ethaddr")) { +- priv->cells[idx].raw_len = strlen(value); +- priv->cells[idx].bytes = ETH_ALEN; +- priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; + } +- } + +- if (WARN_ON(idx != priv->ncells)) +- priv->ncells = idx; ++ nvmem_add_one_cell(nvmem, &info); ++ } + + return 0; + } +@@ -209,7 +199,6 @@ static int u_boot_env_probe(struct platf + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct u_boot_env *priv; +- int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -224,17 +213,15 @@ static int u_boot_env_probe(struct platf + return PTR_ERR(priv->mtd); + } + +- err = u_boot_env_parse(priv); +- if (err) +- return err; +- + config.dev = dev; +- config.cells = priv->cells; +- config.ncells = priv->ncells; + config.priv = priv; + config.size = priv->mtd->size; + +- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++ priv->nvmem = devm_nvmem_register(dev, &config); ++ if (IS_ERR(priv->nvmem)) ++ return PTR_ERR(priv->nvmem); ++ ++ return u_boot_env_parse(priv); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch b/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch new file mode 100644 index 0000000000..70abc7cf14 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch @@ -0,0 +1,81 @@ +From a832556d23c5a11115f300011a5874d6107a0d62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:19 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem device helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use nvmem_dev_size() and nvmem_device_read() to make this driver less +mtd dependent. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-4-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -127,27 +127,34 @@ static int u_boot_env_add_cells(struct u + + static int u_boot_env_parse(struct u_boot_env *priv) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + size_t data_offset; + size_t data_len; ++ size_t dev_size; + uint32_t crc32; + uint32_t calc; +- size_t bytes; + uint8_t *buf; ++ int bytes; + int err; + +- buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kcalloc(1, dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + +- err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); +- if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { +- dev_err(dev, "Failed to read from mtd: %d\n", err); ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; + goto err_kfree; + } + +@@ -169,8 +176,8 @@ static int u_boot_env_parse(struct u_boo + break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); +- crc32_data_len = priv->mtd->size - crc32_data_offset; +- data_len = priv->mtd->size - data_offset; ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { +@@ -179,7 +186,7 @@ static int u_boot_env_parse(struct u_boo + goto err_kfree; + } + +- buf[priv->mtd->size - 1] = '\0'; ++ buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); + if (err) + dev_err(dev, "Failed to add cells: %d\n", err); diff --git a/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch b/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch new file mode 100644 index 0000000000..273cfed874 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch @@ -0,0 +1,62 @@ +From 6bafe07c930676d6430be471310958070816a595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:20 +0100 +Subject: [PATCH] nvmem: u-boot-env: improve coding style +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Prefer kzalloc() over kcalloc() + See memory-allocation.rst which says: "to be on the safe side it's + best to use routines that set memory to zero, like kzalloc()" +2. Drop dev_err() for u_boot_env_add_cells() fail + It can fail only on -ENOMEM. We don't want to print error then. +3. Add extra "crc32_addr" variable + It makes code reading header's crc32 easier to understand / review. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-5-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -132,6 +132,7 @@ static int u_boot_env_parse(struct u_boo + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; ++ __le32 *crc32_addr; + size_t data_offset; + size_t data_len; + size_t dev_size; +@@ -143,7 +144,7 @@ static int u_boot_env_parse(struct u_boo + + dev_size = nvmem_dev_size(nvmem); + +- buf = kcalloc(1, dev_size, GFP_KERNEL); ++ buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; +@@ -175,7 +176,8 @@ static int u_boot_env_parse(struct u_boo + data_offset = offsetof(struct u_boot_env_image_broadcom, data); + break; + } +- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + +@@ -188,8 +190,6 @@ static int u_boot_env_parse(struct u_boo + + buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- if (err) +- dev_err(dev, "Failed to add cells: %d\n", err); + + err_kfree: + kfree(buf); diff --git a/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 6cd798fc5d..daa970884e 100644 --- a/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -107,7 +107,7 @@ Signed-off-by: Jakub Kicinski init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1013,6 +1013,39 @@ struct phy_driver { +@@ -1022,6 +1022,39 @@ struct phy_driver { int (*led_blink_set)(struct phy_device *dev, u8 index, unsigned long *delay_on, unsigned long *delay_off); diff --git a/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch b/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch index f82dc1428a..15af039a16 100644 --- a/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch +++ b/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch @@ -148,7 +148,7 @@ Signed-off-by: Greg Kroah-Hartman * of_find_node_by_phandle - Find a node given a phandle --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -2315,8 +2315,8 @@ of_register_spi_device(struct spi_contro +@@ -2326,8 +2326,8 @@ of_register_spi_device(struct spi_contro } /* Select device driver */ diff --git a/target/linux/generic/backport-6.1/894-v6.8-net-ethtool-implement-ethtool_puts.patch b/target/linux/generic/backport-6.1/894-v6.8-net-ethtool-implement-ethtool_puts.patch new file mode 100644 index 0000000000..5094a6d774 --- /dev/null +++ b/target/linux/generic/backport-6.1/894-v6.8-net-ethtool-implement-ethtool_puts.patch @@ -0,0 +1,139 @@ +From mboxrd@z Thu Jan 1 00:00:00 1970 +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sMUeie/T" +Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84BB8D6D + for ; Wed, 6 Dec 2023 15:16:16 -0800 (PST) +Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-db5416d0fccso403298276.1 + for ; Wed, 06 Dec 2023 15:16:16 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20230601; t=1701904575; x=1702509375; darn=vger.kernel.org; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=sMUeie/TxdytzC0EyT11QWi1TqTtiv7KCTs1F2vLmUUvPKNA3+1MHFo8ECW+0gQuDE + FGrgdZKGK5mXQgkF0N3JiSLvKO8tpQOIB57JLCG5IVy5dr2vVv0ExU3Dag2Cc4oBIBIO + w/cH95O1oPlvluIpATmAsxenVr7mFomU63BqYiRGLaEhWeb2hJ636GO8lubtsDfdFFoi + GPOL2tQwV93VnqmywBBpFaNAULN0UoCFhfkKv5prvpkXq19sWI7zyorVZ+rdTYem5m4T + dXsDaLXPtC3Dh2JOad1duSQIah/wCHYYUcV3IoFhwj2y0Uk/TTCrnZPORweSADcEy6Ho + vDrA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1701904575; x=1702509375; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=Dmc6aSntxPlxAk72zVO1G9WoZnFtLolxENlLscYYAHG3VE+PQ8gGN2rPzcGoKb2Btb + 4b0PvjOzSlPQyghahdhdlz04RtAeeGG/MkfNiYjFql5OifIoovb51kroiPYrVsa7Ps7Y + +Pxug0+NPdTm5s9TNz940ZKl3GRME8UTmVxpWJRX03XMOqb6Wgsh2SK9ahXKc4yRsi62 + 3a3J72WmmSgvimxwM/99fXwvoUQpiv2J1xCoqc1Ng4q4qSuZvzmHN7ZTGaUhLxOqLeLK + 3W4RKHW6rZ7UjppuB6I3NXW+D344By2rdKp1sRXpjdQ0GS3YUcvlRETcJBXJudHfQP5Y + CLOw== +X-Gm-Message-State: AOJu0YzdCTLdwny+N99zeMgyKqFsEZhfIhL2cbgKA6zC1U/OLkxxRLoM + XrYVBC9DmxCGmP4o+M/Z/kHUew/9faHlCiLGxw== +X-Google-Smtp-Source: AGHT+IFRXxBV6JuX5Cl/k2o1+WKkCwkR8j20MJSkmoGCedPAtqFttH8OVh1/6vdfnq8MPN++A2h89peZQhyG8OsJ8A== +X-Received: from jstitt-linux1.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:23b5]) + (user=justinstitt job=sendgmr) by 2002:a25:dac7:0:b0:da0:3117:f35 with SMTP + id n190-20020a25dac7000000b00da031170f35mr28652ybf.3.1701904575576; Wed, 06 + Dec 2023 15:16:15 -0800 (PST) +Date: Wed, 06 Dec 2023 23:16:10 +0000 +In-Reply-To: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +Precedence: bulk +X-Mailing-List: bpf@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +Mime-Version: 1.0 +References: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +X-Developer-Key: i=justinstitt@google.com; a=ed25519; pk=tC3hNkJQTpNX/gLKxTNQKDmiQl6QjBNCGKJINqAdJsE= +X-Developer-Signature: v=1; a=ed25519-sha256; t=1701904573; l=1840; + i=justinstitt@google.com; s=20230717; h=from:subject:message-id; + bh=UMdetIL2ZsPIkSodqhw2fM21NHJVjCu0lRImFuNhVoM=; b=a8rMnXfVVQ5gsxHWG4WRMwOLxZgflqXZtNuKx26vv4DwYvvCtCiYjl3f1frOjV/Ul2kaxq5g/ + b/UOv678JKCDASVokxG5GJifAnU7/kqRxdhcwfRkrD8RUfcsmiZOfyF +X-Mailer: b4 0.12.3 +Message-ID: <20231206-ethtool_puts_impl-v5-1-5a2528e17bf8@google.com> +Subject: [PATCH net-next v5 1/3] ethtool: Implement ethtool_puts() +From: justinstitt@google.com +To: "David S. Miller" , Eric Dumazet , + Jakub Kicinski , Paolo Abeni , Shay Agroskin , + Arthur Kiyanovski , David Arinzon , Noam Dagan , + Saeed Bishara , Rasesh Mody , + Sudarsana Kalluru , GR-Linux-NIC-Dev@marvell.com, + Dimitris Michailidis , Yisen Zhuang , + Salil Mehta , Jesse Brandeburg , + Tony Nguyen , Louis Peens , + Shannon Nelson , Brett Creeley , drivers@pensando.io, + "K. Y. Srinivasan" , Haiyang Zhang , Wei Liu , + Dexuan Cui , Ronak Doshi , + VMware PV-Drivers Reviewers , Andy Whitcroft , Joe Perches , + Dwaipayan Ray , Lukas Bulwahn , + Hauke Mehrtens , Andrew Lunn , + Florian Fainelli , Vladimir Oltean , + "=?utf-8?q?Ar=C4=B1n=C3=A7_=C3=9CNAL?=" , Daniel Golle , + Landen Chao , DENG Qingfang , + Sean Wang , Matthias Brugger , + AngeloGioacchino Del Regno , + Linus Walleij , + "=?utf-8?q?Alvin_=C5=A0ipraga?=" , Wei Fang , + Shenwei Wang , Clark Wang , + NXP Linux Team , Lars Povlsen , + Steen Hegelund , Daniel Machon , + UNGLinuxDriver@microchip.com, Jiawen Wu , + Mengyuan Lou , Heiner Kallweit , + Russell King , Alexei Starovoitov , + Daniel Borkmann , Jesper Dangaard Brouer , + John Fastabend +Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, + Nick Desaulniers , Nathan Chancellor , + Kees Cook , intel-wired-lan@lists.osuosl.org, + oss-drivers@corigine.com, linux-hyperv@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, + bpf@vger.kernel.org, Justin Stitt +Content-Type: text/plain; charset="utf-8" + +Use strscpy() to implement ethtool_puts(). + +Functionally the same as ethtool_sprintf() when it's used with two +arguments or with just "%s" format specifier. + +Signed-off-by: Justin Stitt +--- + include/linux/ethtool.h | 13 +++++++++++++ + net/ethtool/ioctl.c | 7 +++++++ + 2 files changed, 20 insertions(+) + +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -843,4 +843,17 @@ int ethtool_get_phc_vclocks(struct net_d + * next string. + */ + extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...); ++ ++/** ++ * ethtool_puts - Write string to ethtool string data ++ * @data: Pointer to a pointer to the start of string to update ++ * @str: String to write ++ * ++ * Write string to *data without a trailing newline. Update *data ++ * to point at start of next string. ++ * ++ * Prefer this function to ethtool_sprintf() when given only ++ * two arguments or if @fmt is just "%s". ++ */ ++extern void ethtool_puts(u8 **data, const char *str); + #endif /* _LINUX_ETHTOOL_H */ +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1974,6 +1974,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * + } + EXPORT_SYMBOL(ethtool_sprintf); + ++void ethtool_puts(u8 **data, const char *str) ++{ ++ strscpy(*data, str, ETH_GSTRING_LEN); ++ *data += ETH_GSTRING_LEN; ++} ++EXPORT_SYMBOL(ethtool_puts); ++ + static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) + { + struct ethtool_value id; diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index d11c946dbc..c6301662f7 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -605,6 +605,7 @@ CONFIG_BASE_SMALL=0 # CONFIG_BAYCOM_SER_FDX is not set # CONFIG_BAYCOM_SER_HDX is not set # CONFIG_BCACHE is not set +# CONFIG_BCM2712_MIP is not set # CONFIG_BCM47XX is not set # CONFIG_BCM54140_PHY is not set # CONFIG_BCM63XX is not set @@ -1036,6 +1037,8 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_PWM is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_QCOM is not set +# CONFIG_COMMON_CLK_RP1 is not set +# CONFIG_COMMON_CLK_RP1_SDIO is not set # CONFIG_COMMON_CLK_RS9_PCIE is not set # CONFIG_COMMON_CLK_SI514 is not set # CONFIG_COMMON_CLK_SI5341 is not set @@ -1725,6 +1728,9 @@ CONFIG_DQL=y # CONFIG_DRM_RCAR_USE_LVDS is not set # CONFIG_DRM_RCAR_USE_MIPI_DSI is not set # CONFIG_DRM_ROCKCHIP is not set +# CONFIG_DRM_RP1_DPI is not set +# CONFIG_DRM_RP1_DSI is not set +# CONFIG_DRM_RP1_VEC is not set # CONFIG_DRM_SII902X is not set # CONFIG_DRM_SII9234 is not set # CONFIG_DRM_SIL_SII8620 is not set @@ -2083,6 +2089,7 @@ CONFIG_FB_NOTIFY=y # CONFIG_FB_PXA is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_RIVA is not set +# CONFIG_FB_RPISENSE is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set @@ -2283,6 +2290,7 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_AMDPT is not set # CONFIG_GPIO_AMD_FCH is not set # CONFIG_GPIO_BCM_KONA is not set +# CONFIG_GPIO_BRCMSTB is not set # CONFIG_GPIO_BT8XX is not set # CONFIG_GPIO_CADENCE is not set # CONFIG_GPIO_CASCADE is not set @@ -2853,6 +2861,7 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_POWERMATE is not set # CONFIG_INPUT_PWM_BEEPER is not set # CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_RASPBERRYPI_BUTTON is not set # CONFIG_INPUT_REGULATOR_HAPTIC is not set # CONFIG_INPUT_SOC_BUTTON_ARRAY is not set # CONFIG_INPUT_SPARSEKMAP is not set @@ -3609,6 +3618,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_PM8921_CORE is not set # CONFIG_MFD_PM8XXX is not set # CONFIG_MFD_QCOM_PM8008 is not set +# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set # CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_RETU is not set @@ -3618,6 +3628,8 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_ROHM_BD71828 is not set # CONFIG_MFD_ROHM_BD718XX is not set # CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_RP1 is not set +# CONFIG_MFD_RPISENSE_CORE is not set # CONFIG_MFD_RSMU_I2C is not set # CONFIG_MFD_RSMU_SPI is not set # CONFIG_MFD_RT4831 is not set @@ -4839,6 +4851,7 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHYLIB is not set # CONFIG_PHYLIB_LEDS is not set # CONFIG_PHYS_ADDR_T_64BIT is not set +# CONFIG_PHY_BRCM_USB is not set # CONFIG_PHY_CADENCE_DP is not set # CONFIG_PHY_CADENCE_DPHY is not set # CONFIG_PHY_CADENCE_DPHY_RX is not set @@ -4875,6 +4888,7 @@ CONFIG_PINCONF=y # CONFIG_PINCTRL is not set # CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_AXP209 is not set +# CONFIG_PINCTRL_BCM2712 is not set # CONFIG_PINCTRL_CEDARFORK is not set # CONFIG_PINCTRL_CY8C95X0 is not set # CONFIG_PINCTRL_EXYNOS is not set @@ -4895,6 +4909,7 @@ CONFIG_PINCONF=y # CONFIG_PINCTRL_MTK_V2 is not set # CONFIG_PINCTRL_OCELOT is not set # CONFIG_PINCTRL_PISTACHIO is not set +# CONFIG_PINCTRL_RP1 is not set # CONFIG_PINCTRL_SC7280 is not set # CONFIG_PINCTRL_SC8180X is not set # CONFIG_PINCTRL_SDX55 is not set @@ -5053,6 +5068,7 @@ CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 # CONFIG_PWM_MEDIATEK is not set # CONFIG_PWM_PCA9685 is not set # CONFIG_PWM_RASPBERRYPI_POE is not set +# CONFIG_PWM_RP1 is not set # CONFIG_PWM_XILINX is not set CONFIG_PWRSEQ_EMMC=y # CONFIG_PWRSEQ_SD8787 is not set @@ -5127,6 +5143,7 @@ CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDSTRUCT_NONE is not set # CONFIG_RAPIDIO is not set # CONFIG_RAS is not set +# CONFIG_RASPBERRYPI_GPIOMEM is not set # CONFIG_RBTREE_TEST is not set # CONFIG_RCU_BOOST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 @@ -5251,6 +5268,7 @@ CONFIG_REISERFS_FS_XATTR=y # CONFIG_RENESAS_PHY is not set # CONFIG_RESET_ATH79 is not set # CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_BRCMSTB is not set # CONFIG_RESET_BRCMSTB_RESCAL is not set # CONFIG_RESET_CONTROLLER is not set # CONFIG_RESET_IMX7 is not set @@ -5779,6 +5797,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_Q54SJ108A2 is not set # CONFIG_SENSORS_RM3100_I2C is not set # CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSORS_RP1_ADC is not set # CONFIG_SENSORS_SBRMI is not set # CONFIG_SENSORS_SBTSI is not set # CONFIG_SENSORS_SCH5627 is not set @@ -6593,6 +6612,7 @@ CONFIG_STDBINUTILS=y # CONFIG_STMMAC_PCI is not set # CONFIG_STMMAC_PLATFORM is not set # CONFIG_STMMAC_SELFTESTS is not set +# CONFIG_STMPE_ADC is not set # CONFIG_STM_DUMMY is not set # CONFIG_STM_SOURCE_CONSOLE is not set CONFIG_STP=y @@ -7510,6 +7530,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_BT856 is not set # CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_BU64754 is not set # CONFIG_VIDEO_CADENCE is not set # CONFIG_VIDEO_CADENCE_CSI2RX is not set # CONFIG_VIDEO_CADENCE_CSI2TX is not set @@ -7603,6 +7624,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_OV5675 is not set # CONFIG_VIDEO_OV5693 is not set # CONFIG_VIDEO_OV5695 is not set +# CONFIG_VIDEO_OV64A40 is not set # CONFIG_VIDEO_OV6650 is not set # CONFIG_VIDEO_OV7251 is not set # CONFIG_VIDEO_OV7640 is not set diff --git a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch index 29050d38ea..c4a915956e 100644 --- a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch +++ b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch @@ -7,20 +7,17 @@ PHYs AQR113C and AQR813. Signed-off-by: Birger Koblitz ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -20,8 +20,10 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 -+#define PHY_ID_AQR113C 0x31c31c12 +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -23,6 +23,7 @@ #define PHY_ID_AQCS109 0x03a1b5c2 #define PHY_ID_AQR405 0x03a1b4b0 + #define PHY_ID_AQR113C 0x31c31c12 +#define PHY_ID_AQR813 0x31c31cb2 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -381,6 +383,49 @@ static int aqr107_read_rate(struct phy_d +@@ -360,6 +361,49 @@ static int aqr107_read_rate(struct phy_d return 0; } @@ -70,7 +67,7 @@ Signed-off-by: Birger Koblitz static int aqr107_read_status(struct phy_device *phydev) { int val, ret; -@@ -511,7 +556,7 @@ static void aqr107_chip_info(struct phy_ +@@ -499,7 +543,7 @@ static void aqr107_chip_info(struct phy_ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); @@ -79,35 +76,19 @@ Signed-off-by: Birger Koblitz fw_major, fw_minor, build_id, prov_id); } -@@ -719,6 +764,24 @@ static struct phy_driver aqr_driver[] = +@@ -762,7 +806,7 @@ static struct phy_driver aqr_driver[] = + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, ++ .read_status = aqr113c_read_status, + .get_tunable = aqr107_get_tunable, + .set_tunable = aqr107_set_tunable, + .suspend = aqr107_suspend, +@@ -772,6 +816,24 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, - { -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), -+ .name = "Aquantia AQR113C", -+ .probe = aqr107_probe, -+ .config_init = aqr107_config_init, -+ .config_aneg = aqr_config_aneg, -+ .config_intr = aqr_config_intr, -+ .handle_interrupt = aqr_handle_interrupt, -+ .read_status = aqr113c_read_status, -+ .get_tunable = aqr107_get_tunable, -+ .set_tunable = aqr107_set_tunable, -+ .suspend = aqr107_suspend, -+ .resume = aqr107_resume, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+ .link_change_notify = aqr107_link_change_notify, -+}, -+{ - PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), - .name = "Aquantia AQCS109", - .probe = aqr107_probe, -@@ -744,6 +807,24 @@ static struct phy_driver aqr_driver[] = - .handle_interrupt = aqr_handle_interrupt, - .read_status = aqr_read_status, - }, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR813), + .name = "Aquantia AQR813", @@ -129,13 +110,10 @@ Signed-off-by: Birger Koblitz }; module_phy_driver(aqr_driver); -@@ -754,8 +835,10 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, +@@ -785,6 +847,7 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, { } }; diff --git a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch index 262a58036e..b03b4a674f 100644 --- a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch @@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3597,6 +3597,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3600,6 +3600,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index 211696c568..6ec0db2526 100644 --- a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -10,24 +10,21 @@ different firmware on the PHY. Signed-off-by: Alex Marginean --- - drivers/net/phy/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -20,9 +20,11 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 -+#define PHY_ID_AQR112 0x03a1b662 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -24,6 +24,8 @@ #define PHY_ID_AQR405 0x03a1b4b0 -+#define PHY_ID_AQR412 0x03a1b712 + #define PHY_ID_AQR113C 0x31c31c12 #define PHY_ID_AQR813 0x31c31cb2 ++#define PHY_ID_AQR112 0x03a1b662 ++#define PHY_ID_AQR412 0x03a1b712 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 -@@ -135,6 +137,29 @@ + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -96,6 +98,29 @@ #define AQR107_OP_IN_PROG_SLEEP 1000 #define AQR107_OP_IN_PROG_TIMEOUT 100000 @@ -57,7 +54,7 @@ Signed-off-by: Alex Marginean struct aqr107_hw_stat { const char *name; int reg; -@@ -266,6 +291,51 @@ static int aqr_config_aneg(struct phy_de +@@ -227,6 +252,51 @@ static int aqr_config_aneg(struct phy_de return genphy_c45_check_and_restart_aneg(phydev, changed); } @@ -109,7 +106,7 @@ Signed-off-by: Alex Marginean static int aqr_config_intr(struct phy_device *phydev) { bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -825,6 +895,30 @@ static struct phy_driver aqr_driver[] = +@@ -834,6 +904,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -140,15 +137,12 @@ Signed-off-by: Alex Marginean }; module_phy_driver(aqr_driver); -@@ -835,9 +929,11 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, +@@ -848,6 +942,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, { } }; + diff --git a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch index 7d16c8aa28..33b182eab9 100644 --- a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch +++ b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch @@ -9,12 +9,12 @@ these protocols leads to link issues on system side. Signed-off-by: Alex Marginean --- - drivers/net/phy/aquantia_main.c | 8 +++++++- + drivers/net/phy/aquantia/aquantia_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -324,10 +324,16 @@ static int aqr_config_aneg_set_prot(stru +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -285,10 +285,16 @@ static int aqr_config_aneg_set_prot(stru phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, aquantia_syscfg[if_type].start_rate); diff --git a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch index d03c3430fa..a31b327f9e 100644 --- a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch +++ b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch @@ -5,20 +5,20 @@ Subject: [PATCH] PONRTSYS-8842: aquantia: Add AQR113 driver support Add a new entry for AQR113 PHY_ID --- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -21,6 +21,7 @@ - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -26,6 +26,7 @@ + #define PHY_ID_AQR813 0x31c31cb2 #define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR412 0x03a1b712 +#define PHY_ID_AQR113 0x31c31c40 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 - #define PHY_ID_AQR405 0x03a1b4b0 -@@ -914,6 +915,14 @@ static struct phy_driver aqr_driver[] = + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -923,6 +924,14 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -33,11 +33,11 @@ Add a new entry for AQR113 PHY_ID PHY_ID_MATCH_MODEL(PHY_ID_AQR412), .name = "Aquantia AQR412", .probe = aqr107_probe, -@@ -936,6 +945,7 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +@@ -950,6 +959,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { } + }; + diff --git a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index 9821c0c86e..b2f79f4d58 100644 --- a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -7,21 +7,21 @@ As advised by Ian Chang this PHY is used in Puzzle devices. Signed-off-by: Daniel Golle --- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -21,6 +21,8 @@ - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -27,6 +27,8 @@ #define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR412 0x03a1b712 + #define PHY_ID_AQR113 0x31c31c40 +#define PHY_ID_AQR112C 0x03a1b790 +#define PHY_ID_AQR112R 0x31c31d12 - #define PHY_ID_AQR113 0x31c31c40 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 -@@ -915,6 +917,30 @@ static struct phy_driver aqr_driver[] = + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -924,6 +926,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -52,12 +52,12 @@ Signed-off-by: Daniel Golle PHY_ID_MATCH_MODEL(PHY_ID_AQR113), .name = "Aquantia AQR113", .config_aneg = aqr_config_aneg, -@@ -945,6 +971,8 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +@@ -960,6 +986,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { } + }; + diff --git a/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch b/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch index e14a5f1747..3d2c86169b 100644 --- a/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch +++ b/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch @@ -10,18 +10,18 @@ This is a 5GbE chip but it reports support for 10G. Implement config_init() to set max speed to 5G. Signed-off-by: Thomas Kupper ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -20,6 +20,8 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -24,6 +24,8 @@ + #define PHY_ID_AQR405 0x03a1b4b0 + #define PHY_ID_AQR113C 0x31c31c12 + #define PHY_ID_AQR813 0x31c31cb2 +#define PHY_ID_AQR111 0x03a1b610 +#define PHY_ID_AQR111B0 0x03a1b612 #define PHY_ID_AQR112 0x03a1b662 - #define PHY_ID_AQR112C 0x03a1b790 - #define PHY_ID_AQR112R 0x31c31d12 -@@ -686,6 +688,33 @@ static int aqcs109_config_init(struct ph + #define PHY_ID_AQR412 0x03a1b712 + #define PHY_ID_AQR113 0x31c31c40 +@@ -676,6 +678,33 @@ static int aqcs109_config_init(struct ph return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); } @@ -55,7 +55,7 @@ Signed-off-by: Thomas Kupper static void aqr107_link_change_notify(struct phy_device *phydev) { u8 fw_major, fw_minor; -@@ -905,6 +934,42 @@ static struct phy_driver aqr_driver[] = +@@ -914,6 +943,42 @@ static struct phy_driver aqr_driver[] = .link_change_notify = aqr107_link_change_notify, }, { @@ -98,12 +98,12 @@ Signed-off-by: Thomas Kupper PHY_ID_MATCH_MODEL(PHY_ID_AQR112), .name = "Aquantia AQR112", .probe = aqr107_probe, -@@ -970,6 +1035,8 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +@@ -983,6 +1048,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, diff --git a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch index 60f02f7143..0060fbbd2a 100644 --- a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch @@ -43,7 +43,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1146,6 +1151,11 @@ static const struct usb_device_id option +@@ -1147,6 +1152,11 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, @@ -55,7 +55,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support /* Quectel products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), -@@ -1187,6 +1197,11 @@ static const struct usb_device_id option +@@ -1188,6 +1198,11 @@ static const struct usb_device_id option .driver_info = ZLP }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = RSVD(4) }, diff --git a/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch b/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch index a463bf7c4e..f93d84c6a4 100644 --- a/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch +++ b/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch @@ -57,7 +57,7 @@ Signed-off-by: Daniel Golle const unsigned long *advertising); --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -931,7 +931,6 @@ static int phylink_change_inband_advert( +@@ -934,7 +934,6 @@ static int phylink_change_inband_advert( return 0; } @@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle static void phylink_mac_pcs_get_state(struct phylink *pl, struct phylink_link_state *state) { -@@ -3015,6 +3014,52 @@ void phylink_mii_c22_pcs_get_state(struc +@@ -3019,6 +3018,52 @@ void phylink_mii_c22_pcs_get_state(struc EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state); /** @@ -118,7 +118,7 @@ Signed-off-by: Daniel Golle * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS * advertisement * @pcs: a pointer to a &struct mdio_device. -@@ -3086,6 +3131,46 @@ int phylink_mii_c22_pcs_set_advertisemen +@@ -3090,6 +3135,46 @@ int phylink_mii_c22_pcs_set_advertisemen EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement); /** diff --git a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch index 11f4f556e8..ab4d636956 100644 --- a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch @@ -77,7 +77,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -1987,9 +2001,11 @@ static void __sk_free(struct sock *sk) +@@ -1994,9 +2008,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); diff --git a/target/linux/generic/hack-5.15/902-debloat_proc.patch b/target/linux/generic/hack-5.15/902-debloat_proc.patch index 768d3e1f0c..dcdad4ca69 100644 --- a/target/linux/generic/hack-5.15/902-debloat_proc.patch +++ b/target/linux/generic/hack-5.15/902-debloat_proc.patch @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -3881,6 +3881,8 @@ static __net_initdata struct pernet_oper +@@ -3889,6 +3889,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index 386291bfe8..9ff45a414e 100644 --- a/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch +++ b/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -654,7 +654,7 @@ Signed-off-by: Felix Fietkau +}; + +static int nf_flow_rule_route_inet(struct net *net, -+ const struct flow_offload *flow, ++ struct flow_offload *flow, + enum flow_offload_tuple_dir dir, + struct nf_flow_rule *flow_rule) +{ @@ -755,7 +755,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct nf_flowtable *flowtable, struct flow_offload *flow, void *data), void *data) -@@ -436,6 +434,7 @@ static void nf_flow_offload_gc_step(stru +@@ -443,6 +441,7 @@ static void nf_flow_offload_gc_step(stru nf_flow_offload_stats(flow_table, flow); } } @@ -785,7 +785,7 @@ Signed-off-by: Felix Fietkau +#endif /* _XT_FLOWOFFLOAD_H */ --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h -@@ -280,6 +280,11 @@ void nf_flow_table_free(struct nf_flowta +@@ -293,6 +293,11 @@ void nf_flow_table_free(struct nf_flowta void flow_offload_teardown(struct flow_offload *flow); diff --git a/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch index 9ce8f82af0..b0be9dfdcb 100644 --- a/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1707,6 +1707,7 @@ enum netdev_priv_flags { +@@ -1730,6 +1730,7 @@ enum netdev_priv_flags { /* was IFF_LIVE_RENAME_OK */ IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau }; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN -@@ -1740,6 +1741,7 @@ enum netdev_priv_flags { +@@ -1763,6 +1764,7 @@ enum netdev_priv_flags { #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR @@ -35,7 +35,7 @@ Signed-off-by: Felix Fietkau /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { -@@ -2108,6 +2110,11 @@ struct net_device { +@@ -2131,6 +2133,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau const struct header_ops *header_ops; unsigned char operstate; -@@ -2183,6 +2190,10 @@ struct net_device { +@@ -2206,6 +2213,10 @@ struct net_device { struct mctp_dev __rcu *mctp_ptr; #endif @@ -105,7 +105,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3604,6 +3604,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3607,6 +3607,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch index 481185122f..51f939356f 100644 --- a/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch @@ -43,7 +43,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1146,6 +1151,11 @@ static const struct usb_device_id option +@@ -1147,6 +1152,11 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, @@ -55,7 +55,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support /* Quectel products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), -@@ -1187,6 +1197,11 @@ static const struct usb_device_id option +@@ -1188,6 +1198,11 @@ static const struct usb_device_id option .driver_info = ZLP }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = RSVD(4) }, diff --git a/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch index b4403e82c8..ffa6e8ac60 100644 --- a/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch @@ -79,7 +79,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -2180,9 +2194,11 @@ static void __sk_free(struct sock *sk) +@@ -2187,9 +2201,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); diff --git a/target/linux/generic/hack-6.1/902-debloat_proc.patch b/target/linux/generic/hack-6.1/902-debloat_proc.patch index a5db9b21c1..0d844994aa 100644 --- a/target/linux/generic/hack-6.1/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.1/902-debloat_proc.patch @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4105,6 +4105,8 @@ static __net_initdata struct pernet_oper +@@ -4113,6 +4113,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch new file mode 100644 index 0000000000..f420d210c2 --- /dev/null +++ b/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Thu, 4 Jan 2024 15:21:21 +0100 +Subject: [PATCH] net: bridge: do not send arp replies if src and target hw + addr is the same + +There are broken devices in the wild that handle duplicate IP address +detection by sending out ARP requests for the IP that they received from a +DHCP server and refuse the address if they get a reply. +When proxyarp is enabled, they would go into a loop of requesting an address +and then NAKing it again. + +Link: https://github.com/openwrt/openwrt/issues/14309 +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_ + if ((p && (p->flags & BR_PROXYARP)) || + (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | + BR_NEIGH_SUPPRESS)))) { +- if (!vid) ++ replied = true; ++ if (!memcmp(n->ha, sha, dev->addr_len)) ++ replied = false; ++ else if (!vid) + br_arp_send(br, p, skb->dev, sip, tip, + sha, n->ha, sha, 0, 0); + else +@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_ + sha, n->ha, sha, + skb->vlan_proto, + skb_vlan_tag_get(skb)); +- replied = true; + } + + /* If we have replied or as long as we know the diff --git a/target/linux/generic/pending-5.15/540-ksmbd-only-v2-leases-handle-the-directory.patch b/target/linux/generic/pending-5.15/540-ksmbd-only-v2-leases-handle-the-directory.patch new file mode 100644 index 0000000000..1bc0e72418 --- /dev/null +++ b/target/linux/generic/pending-5.15/540-ksmbd-only-v2-leases-handle-the-directory.patch @@ -0,0 +1,32 @@ +From cb1d41b99e4afa062f904339666fae2578559718 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Mon, 15 Jan 2024 10:24:54 +0900 +Subject: [PATCH] ksmbd: only v2 leases handle the directory + +When smb2 leases is disable, ksmbd can send oplock break notification +and cause wait oplock break ack timeout. It may appear like hang when +accessing a directory. This patch make only v2 leases handle the +directory. + +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +--- + fs/ksmbd/oplock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ksmbd/oplock.c ++++ b/fs/ksmbd/oplock.c +@@ -1191,6 +1191,12 @@ int smb_grant_oplock(struct ksmbd_work * + bool prev_op_has_lease; + __le32 prev_op_state = 0; + ++ /* Only v2 leases handle the directory */ ++ if (S_ISDIR(file_inode(fp->filp)->i_mode)) { ++ if (!lctx || lctx->version != 2) ++ return 0; ++ } ++ + opinfo = alloc_opinfo(work, pid, tid); + if (!opinfo) + return -ENOMEM; diff --git a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 7aaac96531..071a2ed3e5 100644 --- a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4560,6 +4579,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4557,6 +4576,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -5047,7 +5077,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5044,7 +5074,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6301,6 +6332,8 @@ static int ip6_route_dev_notify(struct n +@@ -6298,6 +6329,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6312,6 +6345,7 @@ static int ip6_route_dev_notify(struct n +@@ -6309,6 +6342,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6503,6 +6537,8 @@ static int __net_init ip6_route_net_init +@@ -6500,6 +6534,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6513,11 +6549,21 @@ static int __net_init ip6_route_net_init +@@ -6510,11 +6546,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6544,6 +6590,8 @@ out: +@@ -6541,6 +6587,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6563,6 +6611,7 @@ static void __net_exit ip6_route_net_exi +@@ -6560,6 +6608,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6646,6 +6695,9 @@ void __init ip6_route_init_special_entri +@@ -6643,6 +6692,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 89b0c9f53c..c6a6c6e797 100644 --- a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau __u8 inner_protocol_type:1; --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6074,6 +6074,9 @@ static enum gro_result dev_gro_receive(s +@@ -6077,6 +6077,9 @@ static enum gro_result dev_gro_receive(s int same_flow; int grow; @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau if (netif_elide_gro(skb->dev)) goto normal; -@@ -8088,6 +8091,48 @@ static void __netdev_adjacent_dev_unlink +@@ -8091,6 +8094,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -8139,6 +8184,7 @@ static int __netdev_upper_dev_link(struc +@@ -8142,6 +8187,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -99,7 +99,7 @@ Signed-off-by: Felix Fietkau ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -8235,6 +8281,7 @@ static void __netdev_upper_dev_unlink(st +@@ -8238,6 +8284,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -107,7 +107,7 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -9054,6 +9101,7 @@ int dev_set_mac_address(struct net_devic +@@ -9057,6 +9104,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; diff --git a/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch b/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch index 723af24770..d2ca7c7b53 100644 --- a/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch +++ b/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c -@@ -7709,7 +7709,7 @@ static int nft_register_flowtable_net_ho +@@ -7736,7 +7736,7 @@ static int nft_register_flowtable_net_ho err = flowtable->data.type->setup(&flowtable->data, hook->ops.dev, FLOW_BLOCK_BIND); diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch index 83587b5c93..f93dca6814 100644 --- a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -843,6 +843,12 @@ struct phy_driver { +@@ -868,6 +868,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch index 685a11f22d..c8d0bc69f9 100644 --- a/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #endif --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -4583,7 +4583,7 @@ static int rps_ipi_queued(struct softnet +@@ -4586,7 +4586,7 @@ static int rps_ipi_queued(struct softnet #ifdef CONFIG_RPS struct softnet_data *mysd = this_cpu_ptr(&softnet_data); @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau sd->rps_ipi_next = mysd->rps_ipi_list; mysd->rps_ipi_list = sd; -@@ -5764,6 +5764,8 @@ static DEFINE_PER_CPU(struct work_struct +@@ -5767,6 +5767,8 @@ static DEFINE_PER_CPU(struct work_struct /* Network device is going away, flush any packets still pending */ static void flush_backlog(struct work_struct *work) { @@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau struct sk_buff *skb, *tmp; struct softnet_data *sd; -@@ -5779,9 +5781,18 @@ static void flush_backlog(struct work_st +@@ -5782,9 +5784,18 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -67,7 +67,7 @@ Signed-off-by: Felix Fietkau skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->process_queue); -@@ -5789,7 +5800,18 @@ static void flush_backlog(struct work_st +@@ -5792,7 +5803,18 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -86,7 +86,7 @@ Signed-off-by: Felix Fietkau } static bool flush_required(int cpu) -@@ -6472,6 +6494,7 @@ static int process_backlog(struct napi_s +@@ -6475,6 +6497,7 @@ static int process_backlog(struct napi_s local_irq_disable(); rps_lock(sd); @@ -94,7 +94,7 @@ Signed-off-by: Felix Fietkau if (skb_queue_empty(&sd->input_pkt_queue)) { /* * Inline a custom version of __napi_complete(). -@@ -6481,7 +6504,8 @@ static int process_backlog(struct napi_s +@@ -6484,7 +6507,8 @@ static int process_backlog(struct napi_s * We can use a plain write instead of clear_bit(), * and we dont need an smp_mb() memory barrier. */ @@ -104,7 +104,7 @@ Signed-off-by: Felix Fietkau again = false; } else { skb_queue_splice_tail_init(&sd->input_pkt_queue, -@@ -6898,6 +6922,57 @@ int dev_set_threaded(struct net_device * +@@ -6901,6 +6925,57 @@ int dev_set_threaded(struct net_device * } EXPORT_SYMBOL(dev_set_threaded); @@ -162,7 +162,7 @@ Signed-off-by: Felix Fietkau void netif_napi_add(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { -@@ -11378,6 +11453,9 @@ static int dev_cpu_dead(unsigned int old +@@ -11381,6 +11456,9 @@ static int dev_cpu_dead(unsigned int old raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -172,7 +172,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_RPS remsd = oldsd->rps_ipi_list; oldsd->rps_ipi_list = NULL; -@@ -11717,6 +11795,7 @@ static int __init net_dev_init(void) +@@ -11720,6 +11798,7 @@ static int __init net_dev_init(void) sd->cpu = i; #endif diff --git a/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 9b111050ee..d07447bcba 100644 --- a/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -36,9 +36,9 @@ Signed-off-by: Srinivas Kandagatla --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c -@@ -182,7 +182,7 @@ static int u_boot_env_parse(struct u_boo - crc32_data_len = priv->mtd->size - crc32_data_offset; - data_len = priv->mtd->size - data_offset; +@@ -181,7 +181,7 @@ static int u_boot_env_parse(struct u_boo + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; - calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); diff --git a/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch new file mode 100644 index 0000000000..f420d210c2 --- /dev/null +++ b/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Thu, 4 Jan 2024 15:21:21 +0100 +Subject: [PATCH] net: bridge: do not send arp replies if src and target hw + addr is the same + +There are broken devices in the wild that handle duplicate IP address +detection by sending out ARP requests for the IP that they received from a +DHCP server and refuse the address if they get a reply. +When proxyarp is enabled, they would go into a loop of requesting an address +and then NAKing it again. + +Link: https://github.com/openwrt/openwrt/issues/14309 +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_ + if ((p && (p->flags & BR_PROXYARP)) || + (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | + BR_NEIGH_SUPPRESS)))) { +- if (!vid) ++ replied = true; ++ if (!memcmp(n->ha, sha, dev->addr_len)) ++ replied = false; ++ else if (!vid) + br_arp_send(br, p, skb->dev, sip, tip, + sha, n->ha, sha, 0, 0); + else +@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_ + sha, n->ha, sha, + skb->vlan_proto, + skb_vlan_tag_get(skb)); +- replied = true; + } + + /* If we have replied or as long as we know the diff --git a/target/linux/generic/pending-6.1/540-ksmbd-only-v2-leases-handle-the-directory.patch b/target/linux/generic/pending-6.1/540-ksmbd-only-v2-leases-handle-the-directory.patch new file mode 100644 index 0000000000..b565fbd5b9 --- /dev/null +++ b/target/linux/generic/pending-6.1/540-ksmbd-only-v2-leases-handle-the-directory.patch @@ -0,0 +1,32 @@ +From 86b7307af26834415e1ba8597319a8b64846346f Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Mon, 15 Jan 2024 10:24:54 +0900 +Subject: [PATCH] ksmbd: only v2 leases handle the directory + +When smb2 leases is disable, ksmbd can send oplock break notification +and cause wait oplock break ack timeout. It may appear like hang when +accessing a directory. This patch make only v2 leases handle the +directory. + +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +--- + fs/smb/server/oplock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -1191,6 +1191,12 @@ int smb_grant_oplock(struct ksmbd_work * + bool prev_op_has_lease; + __le32 prev_op_state = 0; + ++ /* Only v2 leases handle the directory */ ++ if (S_ISDIR(file_inode(fp->filp)->i_mode)) { ++ if (!lctx || lctx->version != 2) ++ return 0; ++ } ++ + opinfo = alloc_opinfo(work, pid, tid); + if (!opinfo) + return -ENOMEM; diff --git a/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 003a0f20ac..72e8de2f1d 100644 --- a/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4543,6 +4562,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4540,6 +4559,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -5036,7 +5066,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5033,7 +5063,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6290,6 +6321,8 @@ static int ip6_route_dev_notify(struct n +@@ -6287,6 +6318,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6301,6 +6334,7 @@ static int ip6_route_dev_notify(struct n +@@ -6298,6 +6331,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6492,6 +6526,8 @@ static int __net_init ip6_route_net_init +@@ -6489,6 +6523,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6502,11 +6538,21 @@ static int __net_init ip6_route_net_init +@@ -6499,11 +6535,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6533,6 +6579,8 @@ out: +@@ -6530,6 +6576,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6552,6 +6600,7 @@ static void __net_exit ip6_route_net_exi +@@ -6549,6 +6597,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6635,6 +6684,9 @@ void __init ip6_route_init_special_entri +@@ -6632,6 +6681,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 094d63dd89..11850c0418 100644 --- a/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2134,6 +2134,8 @@ struct net_device { +@@ -2157,6 +2157,8 @@ struct net_device { struct netdev_hw_addr_list mc; struct netdev_hw_addr_list dev_addrs; @@ -44,7 +44,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -7622,6 +7622,48 @@ static void __netdev_adjacent_dev_unlink +@@ -7625,6 +7625,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -7673,6 +7715,7 @@ static int __netdev_upper_dev_link(struc +@@ -7676,6 +7718,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -7769,6 +7812,7 @@ static void __netdev_upper_dev_unlink(st +@@ -7772,6 +7815,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -109,7 +109,7 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -8821,6 +8865,7 @@ int dev_set_mac_address(struct net_devic +@@ -8824,6 +8868,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; diff --git a/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch index 6050db3f5b..47c742cff0 100644 --- a/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +++ b/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -10,7 +10,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c -@@ -659,6 +659,23 @@ static struct pernet_operations nf_flow_ +@@ -666,6 +666,23 @@ static struct pernet_operations nf_flow_ .exit_batch = nf_flow_table_pernet_exit, }; @@ -34,7 +34,7 @@ Signed-off-by: Pablo Neira Ayuso static int __init nf_flow_table_module_init(void) { int ret; -@@ -671,8 +688,14 @@ static int __init nf_flow_table_module_i +@@ -678,8 +695,14 @@ static int __init nf_flow_table_module_i if (ret) goto out_offload; @@ -49,7 +49,7 @@ Signed-off-by: Pablo Neira Ayuso out_offload: unregister_pernet_subsys(&nf_flow_table_net_ops); return ret; -@@ -680,6 +703,7 @@ out_offload: +@@ -687,6 +710,7 @@ out_offload: static void __exit nf_flow_table_module_exit(void) { diff --git a/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch index 8d2803158e..425f82376b 100644 --- a/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -878,6 +878,12 @@ struct phy_driver { +@@ -887,6 +887,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/target/linux/generic/pending-6.1/713-01-dt-bindings-net-ipq4019-mdio-document-now-supported-.patch b/target/linux/generic/pending-6.1/713-01-dt-bindings-net-ipq4019-mdio-document-now-supported-.patch new file mode 100644 index 0000000000..35258d8541 --- /dev/null +++ b/target/linux/generic/pending-6.1/713-01-dt-bindings-net-ipq4019-mdio-document-now-supported-.patch @@ -0,0 +1,42 @@ +From 85e2038891989e41bc62f6a4625fd5865da8a1a2 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 19:17:02 +0100 +Subject: [PATCH 1/3] dt-bindings: net: ipq4019-mdio: document now supported + clock-frequency + +Document support for clock-frequency and add details on why this +property is needed and what values are supported. + +From internal documentation, while other values are supported, the +correct function of the MDIO bus is not assured hence add only the +suggested supported values to the property enum. + +Signed-off-by: Christian Marangi +--- + .../bindings/net/qcom,ipq4019-mdio.yaml | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/Documentation/devicetree/bindings/net/qcom,ipq4019-mdio.yaml ++++ b/Documentation/devicetree/bindings/net/qcom,ipq4019-mdio.yaml +@@ -38,6 +38,21 @@ properties: + MDIO clock source frequency fixed to 100MHZ, this clock should be specified + by the platform IPQ807x, IPQ60xx and IPQ50xx. + ++ clock-frequency: ++ description: ++ The MDIO bus clock that must be output by the MDIO bus hardware, if ++ absent, the default hardware values are used. ++ ++ MDC rate is feed by an external clock (fixed 100MHz) and is divider ++ internally. The default divider is /256 resulting in the default rate ++ applied of 390KHz. ++ ++ To follow 802.3 standard that instruct up to 2.5MHz by default, if ++ this property is not declared and the divider is set to /256, by ++ default 1.5625Mhz is select. ++ enum: [ 390625, 781250, 1562500, 3125000, 6250000, 12500000 ] ++ default: 1562500 ++ + required: + - compatible + - reg diff --git a/target/linux/generic/pending-6.1/713-02-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch b/target/linux/generic/pending-6.1/713-02-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch new file mode 100644 index 0000000000..809d7a0441 --- /dev/null +++ b/target/linux/generic/pending-6.1/713-02-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch @@ -0,0 +1,204 @@ +From eacf1d2505dfecd3599d558cdade1a2da47fe06d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 18:52:33 +0100 +Subject: [PATCH 2/3] net: mdio: ipq4019: add support for clock-frequency + property + +The IPQ4019 MDIO internally divide the clock feed by AHB based on the +MDIO_MODE reg. On reset or power up, the default value for the +divider is 0xff that reflect the divider set to /256. + +This makes the MDC run at a very low rate, that is, considering AHB is +always fixed to 100Mhz, a value of 390KHz. + +This hasn't have been a problem as MDIO wasn't used for time sensitive +operation, it is now that on IPQ807x is usually mounted with PHY that +requires MDIO to load their firmware (example Aquantia PHY). + +To handle this problem and permit to set the correct designed MDC +frequency for the SoC add support for the standard "clock-frequency" +property for the MDIO node. + +The divider supports value from /1 to /256 and the common value are to +set it to /16 to reflect 6.25Mhz or to /8 on newer platform to reflect +12.5Mhz. + +To scan if the requested rate is supported by the divider, loop with +each supported divider and stop when the requested rate match the final +rate with the current divider. An error is returned if the rate doesn't +match any value. + +On MDIO reset, the divider is restored to the requested value to prevent +any kind of downclocking caused by the divider reverting to a default +value. + +To follow 802.3 spec of 2.5MHz of default value, if divider is set at +/256 and "clock-frequency" is not set in DT, assume nobody set the +divider and try to find the closest MDC rate to 2.5MHz. (in the case of +AHB set to 100MHz, it's 1.5625MHz) + +While at is also document other bits of the MDIO_MODE reg to have a +clear idea of what is actually applied there. + +Documentation of some BITs is skipped as they are marked as reserved and +their usage is not clear (RES 11:9 GENPHY 16:13 RES1 19:17) + +Signed-off-by: Christian Marangi +--- + drivers/net/mdio/mdio-ipq4019.c | 109 ++++++++++++++++++++++++++++++-- + 1 file changed, 103 insertions(+), 6 deletions(-) + +--- a/drivers/net/mdio/mdio-ipq4019.c ++++ b/drivers/net/mdio/mdio-ipq4019.c +@@ -14,6 +14,20 @@ + #include + + #define MDIO_MODE_REG 0x40 ++#define MDIO_MODE_MDC_MODE BIT(12) ++/* 0 = Clause 22, 1 = Clause 45 */ ++#define MDIO_MODE_C45 BIT(8) ++#define MDIO_MODE_DIV_MASK GENMASK(7, 0) ++#define MDIO_MODE_DIV(x) FIELD_PREP(MDIO_MODE_DIV_MASK, (x) - 1) ++#define MDIO_MODE_DIV_1 0x0 ++#define MDIO_MODE_DIV_2 0x1 ++#define MDIO_MODE_DIV_4 0x3 ++#define MDIO_MODE_DIV_8 0x7 ++#define MDIO_MODE_DIV_16 0xf ++#define MDIO_MODE_DIV_32 0x1f ++#define MDIO_MODE_DIV_64 0x3f ++#define MDIO_MODE_DIV_128 0x7f ++#define MDIO_MODE_DIV_256 0xff + #define MDIO_ADDR_REG 0x44 + #define MDIO_DATA_WRITE_REG 0x48 + #define MDIO_DATA_READ_REG 0x4c +@@ -26,9 +40,6 @@ + #define MDIO_CMD_ACCESS_CODE_C45_WRITE 1 + #define MDIO_CMD_ACCESS_CODE_C45_READ 2 + +-/* 0 = Clause 22, 1 = Clause 45 */ +-#define MDIO_MODE_C45 BIT(8) +- + #define IPQ4019_MDIO_TIMEOUT 10000 + #define IPQ4019_MDIO_SLEEP 10 + +@@ -41,6 +52,7 @@ struct ipq4019_mdio_data { + void __iomem *membase; + void __iomem *eth_ldo_rdy; + struct clk *mdio_clk; ++ unsigned int mdc_rate; + }; + + static int ipq4019_mdio_wait_busy(struct mii_bus *bus) +@@ -179,6 +191,38 @@ static int ipq4019_mdio_write(struct mii + return 0; + } + ++static int ipq4019_mdio_set_div(struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* MDC rate is ahb_rate/(MDIO_MODE_DIV + 1) ++ * While supported, internal documentation doesn't ++ * assure correct functionality of the MDIO bus ++ * with divider of 1, 2 or 4. ++ */ ++ for (div = 8; div <= 256; div *= 2) { ++ /* The requested rate is supported by the div */ ++ if (priv->mdc_rate == DIV_ROUND_UP(ahb_rate, div)) { ++ val = readl(priv->membase + MDIO_MODE_REG); ++ val &= ~MDIO_MODE_DIV_MASK; ++ val |= MDIO_MODE_DIV(div); ++ writel(val, priv->membase + MDIO_MODE_REG); ++ ++ return 0; ++ } ++ } ++ ++ /* The requested rate is not supported */ ++ return -EINVAL; ++} ++ + static int ipq_mdio_reset(struct mii_bus *bus) + { + struct ipq4019_mdio_data *priv = bus->priv; +@@ -201,10 +245,58 @@ static int ipq_mdio_reset(struct mii_bus + return ret; + + ret = clk_prepare_enable(priv->mdio_clk); +- if (ret == 0) +- mdelay(10); ++ if (ret) ++ return ret; ++ ++ mdelay(10); + +- return ret; ++ /* Restore MDC rate */ ++ return ipq4019_mdio_set_div(priv); ++} ++ ++static void ipq4019_mdio_select_mdc_rate(struct platform_device *pdev, ++ struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* MDC rate defined in DT, we don't have to decide a default value */ ++ if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", ++ &priv->mdc_rate)) ++ return; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* Check what is the current div set */ ++ val = readl(priv->membase + MDIO_MODE_REG); ++ div = FIELD_GET(MDIO_MODE_DIV_MASK, val); ++ ++ /* div is not set to the default value of /256 ++ * Probably someone changed that (bootloader, other drivers) ++ * Keep this and doesn't overwrite it. ++ */ ++ if (div != MDIO_MODE_DIV_256) { ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div + 1); ++ return; ++ } ++ ++ /* If div is /256 assume nobody have set this value and ++ * try to find one MDC rate that is close the 802.3 spec of ++ * 2.5MHz ++ */ ++ for (div = 256; div >= 8; div /= 2) { ++ /* Stop as soon as we found a divider that ++ * reached the closest value to 2.5MHz ++ */ ++ if (DIV_ROUND_UP(ahb_rate, div) > 2500000) ++ break; ++ ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div); ++ } + } + + static int ipq4019_mdio_probe(struct platform_device *pdev) +@@ -228,6 +320,11 @@ static int ipq4019_mdio_probe(struct pla + if (IS_ERR(priv->mdio_clk)) + return PTR_ERR(priv->mdio_clk); + ++ ipq4019_mdio_select_mdc_rate(pdev, priv); ++ ret = ipq4019_mdio_set_div(priv); ++ if (ret) ++ return ret; ++ + /* The platform resource is provided on the chipset IPQ5018 */ + /* This resource is optional */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); diff --git a/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch b/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch new file mode 100644 index 0000000000..55f116ec5f --- /dev/null +++ b/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch @@ -0,0 +1,25 @@ +From 3b5a603bf66236b956287909556fd7ad4904450c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 19:38:01 +0100 +Subject: [PATCH 3/3] arm64: dts: qcom: ipq8074: add clock-frequency to MDIO + node + +Add clock-frequency to MDIO node to set the MDC rate to 6.25Mhz instead +of using the default value of 390KHz from MDIO default divider. + +Signed-off-by: Christian Marangi +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -263,6 +263,8 @@ + clocks = <&gcc GCC_MDIO_AHB_CLK>; + clock-names = "gcc_mdio_ahb_clk"; + ++ clock-frequency = <6250000>; ++ + status = "disabled"; + }; + diff --git a/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch b/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch index df422e3a08..a7a4bafbb6 100644 --- a/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch +++ b/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch @@ -17,7 +17,7 @@ Signed-off-by: Christian Marangi --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2169,7 +2169,7 @@ struct net_device { +@@ -2192,7 +2192,7 @@ struct net_device { #if IS_ENABLED(CONFIG_AX25) void *ax25_ptr; #endif diff --git a/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch index e50a3ef699..944e4d1869 100644 --- a/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -520,6 +520,7 @@ static inline bool napi_complete(struct +@@ -543,6 +543,7 @@ static inline bool napi_complete(struct } int dev_set_threaded(struct net_device *dev, bool threaded); @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau /** * napi_disable - prevent NAPI from scheduling -@@ -3129,6 +3130,7 @@ struct softnet_data { +@@ -3152,6 +3153,7 @@ struct softnet_data { unsigned int processed; unsigned int time_squeeze; unsigned int received_rps; @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #endif --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -4622,7 +4622,7 @@ static int napi_schedule_rps(struct soft +@@ -4625,7 +4625,7 @@ static int napi_schedule_rps(struct soft struct softnet_data *mysd = this_cpu_ptr(&softnet_data); #ifdef CONFIG_RPS @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau sd->rps_ipi_next = mysd->rps_ipi_list; mysd->rps_ipi_list = sd; -@@ -5803,6 +5803,8 @@ static DEFINE_PER_CPU(struct work_struct +@@ -5806,6 +5806,8 @@ static DEFINE_PER_CPU(struct work_struct /* Network device is going away, flush any packets still pending */ static void flush_backlog(struct work_struct *work) { @@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau struct sk_buff *skb, *tmp; struct softnet_data *sd; -@@ -5817,8 +5819,17 @@ static void flush_backlog(struct work_st +@@ -5820,8 +5822,17 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->process_queue); -@@ -5826,7 +5837,16 @@ static void flush_backlog(struct work_st +@@ -5829,7 +5840,16 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau } static bool flush_required(int cpu) -@@ -5958,6 +5978,7 @@ static int process_backlog(struct napi_s +@@ -5961,6 +5981,7 @@ static int process_backlog(struct napi_s } rps_lock_irq_disable(sd); @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau if (skb_queue_empty(&sd->input_pkt_queue)) { /* * Inline a custom version of __napi_complete(). -@@ -5967,7 +5988,8 @@ static int process_backlog(struct napi_s +@@ -5970,7 +5991,8 @@ static int process_backlog(struct napi_s * We can use a plain write instead of clear_bit(), * and we dont need an smp_mb() memory barrier. */ @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau again = false; } else { skb_queue_splice_tail_init(&sd->input_pkt_queue, -@@ -6383,6 +6405,55 @@ int dev_set_threaded(struct net_device * +@@ -6386,6 +6408,55 @@ int dev_set_threaded(struct net_device * } EXPORT_SYMBOL(dev_set_threaded); @@ -157,7 +157,7 @@ Signed-off-by: Felix Fietkau void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { -@@ -11165,6 +11236,9 @@ static int dev_cpu_dead(unsigned int old +@@ -11168,6 +11239,9 @@ static int dev_cpu_dead(unsigned int old raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_RPS remsd = oldsd->rps_ipi_list; oldsd->rps_ipi_list = NULL; -@@ -11468,6 +11542,7 @@ static int __init net_dev_init(void) +@@ -11471,6 +11545,7 @@ static int __init net_dev_init(void) INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd); spin_lock_init(&sd->defer_lock); diff --git a/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 9b111050ee..d07447bcba 100644 --- a/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -36,9 +36,9 @@ Signed-off-by: Srinivas Kandagatla --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c -@@ -182,7 +182,7 @@ static int u_boot_env_parse(struct u_boo - crc32_data_len = priv->mtd->size - crc32_data_offset; - data_len = priv->mtd->size - data_offset; +@@ -181,7 +181,7 @@ static int u_boot_env_parse(struct u_boo + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; - calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); diff --git a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch index 254e85c284..a3d8bf0488 100644 --- a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch +++ b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch @@ -32,7 +32,7 @@ Signed-off-by: Maxime Chevallier --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17064,6 +17064,13 @@ L: netdev@vger.kernel.org +@@ -17066,6 +17066,13 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/qualcomm/emac/ @@ -1953,7 +1953,7 @@ Signed-off-by: Maxime Chevallier + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(ipqess_stats); i++) -+ ethtool_sprintf(&p, ipqess_stats[i].string); ++ ethtool_puts(&p, ipqess_stats[i].string); + break; + } +} diff --git a/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch index ecf1a05896..7961c9978b 100644 --- a/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch +++ b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch @@ -64,7 +64,7 @@ Signed-off-by: Maxime Chevallier --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17070,6 +17070,7 @@ L: netdev@vger.kernel.org +@@ -17072,6 +17072,7 @@ L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml F: drivers/net/ethernet/qualcomm/ipqess/ diff --git a/target/linux/ipq806x/base-files/etc/board.d/01_leds b/target/linux/ipq806x/base-files/etc/board.d/01_leds index 0b2ce2b7d5..4aab3c9b2c 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/01_leds +++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds @@ -37,6 +37,15 @@ extreme,ap3935) ucidef_set_led_netdev "wan" "wan" "orange:lan1" "eth1" ucidef_set_led_netdev "lan" "lan" "orange:lan2" "eth0" ;; +fortinet,fap-421e) + ucidef_set_led_netdev "eth1-100" "ETH1-100" "amber:eth1" "eth0" "link_100" + ucidef_set_led_netdev "eth1-1000" "ETH1-1000" "yellow:eth1" "eth0" "link_1000" + ucidef_set_led_netdev "eth2-100" "ETH2-100" "amber:eth2" "eth1" "link_100" + ucidef_set_led_netdev "eth2-1000" "ETH2-1000" "yellow:eth2" "eth1" "link_1000" + ucidef_set_led_wlan "wlan2g" "2.4G" "yellow:2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "5G" "yellow:5g" "phy0tpt" + ucidef_set_led_usbport "usb" "USB" "amber:power" "usb1-port1" "usb2-port1" + ;; meraki,mr52) ucidef_set_led_netdev "eth0" "eth0" "green:lan1" "eth0" ucidef_set_led_netdev "eth1" "eth1" "green:lan2" "eth1" diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 7fdda7cfec..a408fc14ac 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -46,8 +46,7 @@ ipq806x_setup_interfaces() ucidef_set_network_device_conduit "lan1" "eth1" ucidef_set_network_device_conduit "wan" "eth0" ;; - edgecore,ecw5410 |\ - extreme,ap3935) + edgecore,ecw5410) ucidef_set_interfaces_lan_wan "eth1" "eth0" ;; qcom,ipq8064-ap161) @@ -56,12 +55,14 @@ ipq806x_setup_interfaces() qcom,ipq8064-db149) ucidef_set_interface_lan "eth1 eth2 eth3 lan1 lan2 lan3 lan4" "wan" ;; + fortinet,fap-421e |\ ubnt,unifi-ac-hd) ucidef_set_interface_lan "eth0 eth1" ;; meraki,mr42) ucidef_set_interface_lan "eth0" ;; + extreme,ap3935 |\ meraki,mr52) ucidef_set_interfaces_lan_wan "eth0" "eth1" ;; diff --git a/target/linux/ipq806x/base-files/etc/board.d/05_compat-version b/target/linux/ipq806x/base-files/etc/board.d/05_compat-version index 74135b0d62..caf65b96d2 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/05_compat-version +++ b/target/linux/ipq806x/base-files/etc/board.d/05_compat-version @@ -14,6 +14,7 @@ case "$(board_name)" in asrock,g10 |\ buffalo,wxr-2533dhp |\ compex,wpq864 |\ + fortinet,fap-421e |\ nec,wg2600hp |\ nec,wg2600hp3 |\ netgear,d7800 |\ diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 7877ecae6b..b3a615a511 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -13,6 +13,7 @@ platform_do_upgrade() { arris,tr4400-v2 |\ askey,rt4230w-rev6 |\ compex,wpq864|\ + fortinet,fap-421e|\ netgear,d7800 |\ netgear,r7500 |\ netgear,r7500v2 |\ diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts new file mode 100644 index 0000000000..1902a2f996 --- /dev/null +++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8064-smb208.dtsi" +#include +#include + +/ { + model = "Fortinet FAP-421E"; + compatible = "fortinet,fap-421e", "qcom,ipq8064"; + + memory@42000000 { + device_type = "memory"; + reg = <0x42000000 0xe000000>; + }; + + reserved-memory { + rsvd@41200000 { + no-map; + reg = <0x41200000 0x300000>; + }; + wifi_dump@44000000 { + no-map; + reg = <0x44000000 0x600000>; + }; + }; + + aliases { + led-boot = &led_power_yellow; + led-failsafe = &led_power_yellow; + led-running = &led_power_yellow; + led-upgrade = &led_power_yellow; + label-mac-device = &gmac0; + }; + + chosen { + bootargs-override = "console=ttyMSM0,9600n8"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 56 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + eth1-amber { + label = "amber:eth1"; + gpios = <&qcom_pinmux 27 GPIO_ACTIVE_LOW>; + }; + + eth1-yellow { + label = "yellow:eth1"; + gpios = <&qcom_pinmux 26 GPIO_ACTIVE_LOW>; + }; + + eth2-amber { + label = "amber:eth2"; + gpios = <&qcom_pinmux 29 GPIO_ACTIVE_LOW>; + }; + + eth2-yellow { + label = "yellow:eth2"; + gpios = <&qcom_pinmux 28 GPIO_ACTIVE_LOW>; + }; + + power-amber { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 53 GPIO_ACTIVE_LOW>; + }; + + led_power_yellow: power-yellow { + label = "yellow:power"; + gpios = <&qcom_pinmux 58 GPIO_ACTIVE_LOW>; + }; + + 2g-yellow { + label = "yellow:2g"; + gpios = <&qcom_pinmux 30 GPIO_ACTIVE_LOW>; + }; + + 5g-yellow { + label = "yellow:5g"; + gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&qcom_pinmux { + button_pins: button_pins { + mux { + bias-pull-up; + drive-strength = <2>; + pins = "gpio56"; + }; + }; + + led_pins: led_pins { + mux { + bias-pull-down; + drive-strength = <2>; + function = "gpio"; + output-low; + pins = "gpio23"; + }; + }; + + rgmii2_pins: rgmii2-pins { + mux { + bias-disable; + drive-strength = <16>; + function = "rgmii2"; + pins = "gpio66"; + }; + }; + + spi_pins: spi_pins { + mux { + pins = "gpio18", "gpio19", "gpio21"; + function = "gsbi5"; + bias-pull-down; + }; + + data { + pins = "gpio18", "gpio19"; + drive-strength = <10>; + }; + + cs { + pins = "gpio20"; + drive-strength = <10>; + bias-pull-up; + }; + + clk { + pins = "gpio21"; + drive-strength = <12>; + }; + }; + + uart0_pins: uart0_pins { + mux { + bias-disable; + drive-strength = <12>; + function = "gsbi7"; + pins = "gpio6", "gpio7"; + }; + }; + + usb_pwr_en_pins: usb_pwr_en_pins { + mux { + pins = "gpio22"; + function = "gpio"; + drive-strength = <12>; + bias-pull-down; + output-low; + }; + }; +}; + +&gsbi7 { + qcom,mode = ; + + status = "okay"; +}; + +&gsbi7_serial{ + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&gsbi5 { + qcom,mode = ; + + status = "okay"; + + spi@1a280000 { + status = "okay"; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + reg = <0>; + m25p,fast-read; + + partition@0 { + label = "SBL1"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "MIBIB"; + reg = <0x20000 0x20000>; + read-only; + }; + + partition@40000 { + label = "SBL2"; + reg = <0x40000 0x40000>; + read-only; + }; + + partition@80000 { + label = "SBL3"; + reg = <0x80000 0x80000>; + read-only; + }; + + partition@100000 { + label = "DDRCONFIG"; + reg = <0x100000 0x10000>; + read-only; + }; + + partition@110000 { + label = "SSD"; + reg = <0x110000 0x10000>; + read-only; + }; + + partition@120000 { + label = "TZ"; + reg = <0x120000 0x80000>; + read-only; + }; + + partition@1a0000 { + label = "RPM"; + reg = <0x1a0000 0x80000>; + read-only; + }; + + partition@220000 { + label = "APPSBL"; + reg = <0x220000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_appsbl_7ff80: mac-address@7ff80 { + compatible = "mac-base"; + reg = <0x7ff80 0xc>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@2a0000 { + label = "APPSBLENV"; + reg = <0x2a0000 0x40000>; + }; + + partition@2e0000 { + label = "ART"; + reg = <0x2e0000 0x40000>; + read-only; + }; + + partition@320000 { + label = "kernel"; + reg = <0x320000 0x600000>; + }; + + partition@920000 { + label = "ubi"; + reg = <0x920000 0x1400000>; + }; + + partition@1d20000 { + label = "reserved"; + reg = <0x1d20000 0x260000>; + read-only; + }; + + partition@1f80000 { + label = "config"; + reg = <0x1f80000 0x80000>; + read-only; + }; + }; + }; +}; + +&hs_phy_1 { + status = "okay"; +}; + +&ss_phy_1 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; + + pinctrl-0 = <&usb_pwr_en_pins>; + pinctrl-names = "default"; +}; + +&pcie0 { + status = "okay"; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + compatible = "pci168c,0040"; + reg = <0x00010000 0 0 0 0>; + + nvmem-cells = <&macaddr_appsbl_7ff80 8>; + nvmem-cell-names = "mac-address"; + }; + }; +}; + +&pcie1 { + status = "okay"; + + max-link-speed = <1>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + compatible = "pci168c,0040"; + reg = <0x00010000 0 0 0 0>; + + nvmem-cells = <&macaddr_appsbl_7ff80 16>; + nvmem-cell-names = "mac-address"; + }; + }; +}; + +&adm_dma { + status = "okay"; +}; + +&mdio0 { + status = "okay"; + + #address-cells = <0x1>; + #size-cells = <0x0>; + gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>, + <&qcom_pinmux 0 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + + phy2: ethernet-phy@2 { + reg = <2>; + }; +}; + +&gmac0 { + status = "okay"; + + phy-mode = "rgmii"; + qcom,id = <0>; + pinctrl-0 = <&rgmii2_pins>; + pinctrl-names = "default"; + nvmem-cells = <&macaddr_appsbl_7ff80 0>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&gmac2 { + status = "okay"; + + phy-mode = "sgmii"; + qcom,id = <2>; + nvmem-cells = <&macaddr_appsbl_7ff80 1>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts index bf65630f18..6d473d43ab 100644 --- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts +++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts @@ -195,6 +195,7 @@ reg = <0x2a0000 0x0010000>; ethaddr: ethaddr { + #nvmem-cell-cells = <1>; }; }; @@ -327,7 +328,7 @@ phy-mode = "rgmii"; phy-handle = <&phy1>; - nvmem-cells = <ðaddr>; + nvmem-cells = <ðaddr 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -344,6 +345,9 @@ phy-mode = "sgmii"; phy-handle = <&phy2>; + + nvmem-cells = <ðaddr 1>; + nvmem-cell-names = "mac-address"; }; &adm_dma { diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index b3743c35e3..98e74e5b11 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -177,6 +177,18 @@ define Device/extreme_ap3935 endef TARGET_DEVICES += extreme_ap3935 +define Device/fortinet_fap-421e + $(call Device/FitImage) + DEVICE_VENDOR := Fortinet + DEVICE_MODEL := FAP-421E + SOC := qcom-ipq8064 + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := fap-421e + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct +endef +TARGET_DEVICES += fortinet_fap-421e + define Device/linksys_ea7500-v1 $(call Device/LegacyImage) $(Device/kernel-size-migration) @@ -228,7 +240,7 @@ define Device/meraki_mr42 BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_LOADADDR = 0x44208000 - DEVICE_PACKAGES := -swconfig -kmod-ata-ahci -kmod-ata-ahci-platform \ + DEVICE_PACKAGES := -kmod-ata-ahci -kmod-ata-ahci-platform \ -kmod-usb-ohci -kmod-usb2 -kmod-usb-ledtrig-usbport \ -kmod-phy-qcom-ipq806x-usb -kmod-usb3 -kmod-usb-dwc3-qcom \ -uboot-envtools ath10k-firmware-qca9887-ct \ @@ -246,7 +258,7 @@ define Device/meraki_mr52 PAGESIZE := 2048 KERNEL_LOADADDR = 0x44208000 DEVICE_DTS_CONFIG := config@2 - DEVICE_PACKAGES := -swconfig -kmod-ata-ahci -kmod-ata-ahci-platform \ + DEVICE_PACKAGES := -kmod-ata-ahci -kmod-ata-ahci-platform \ -kmod-usb-ohci -kmod-usb2 -kmod-usb-ledtrig-usbport \ -kmod-phy-qcom-ipq806x-usb -kmod-usb3 -kmod-usb-dwc3-qcom \ -uboot-envtools ath10k-firmware-qca9887-ct \ diff --git a/target/linux/ipq806x/patches-6.1/120-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch b/target/linux/ipq806x/patches-6.1/001-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/120-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch rename to target/linux/ipq806x/patches-6.1/001-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch diff --git a/target/linux/ipq806x/patches-6.1/131-6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch b/target/linux/ipq806x/patches-6.1/003-v6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch similarity index 98% rename from target/linux/ipq806x/patches-6.1/131-6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch rename to target/linux/ipq806x/patches-6.1/003-v6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch index e542421085..7e65f4cdff 100644 --- a/target/linux/ipq806x/patches-6.1/131-6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch +++ b/target/linux/ipq806x/patches-6.1/003-v6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch @@ -18,7 +18,7 @@ Link: https://lore.kernel.org/r/20221024233817.27410-1-ansuelsmth@gmail.com --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -932,7 +932,6 @@ +@@ -756,7 +756,6 @@ non-removable; cap-sd-highspeed; cap-mmc-highspeed; diff --git a/target/linux/ipq806x/patches-6.1/110-01-thermal-qcom-tsens-init-debugfs-only-with-successful.patch b/target/linux/ipq806x/patches-6.1/004-v6.2-01-thermal-drivers-qcom-tsens-Init-debugfs-only-with-su.patch similarity index 52% rename from target/linux/ipq806x/patches-6.1/110-01-thermal-qcom-tsens-init-debugfs-only-with-successful.patch rename to target/linux/ipq806x/patches-6.1/004-v6.2-01-thermal-drivers-qcom-tsens-Init-debugfs-only-with-su.patch index c9b20a0222..76df0f5681 100644 --- a/target/linux/ipq806x/patches-6.1/110-01-thermal-qcom-tsens-init-debugfs-only-with-successful.patch +++ b/target/linux/ipq806x/patches-6.1/004-v6.2-01-thermal-drivers-qcom-tsens-Init-debugfs-only-with-su.patch @@ -1,18 +1,20 @@ -From 8f32d48a309246a80bdca505968085a484d54408 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Mon, 19 Apr 2021 03:01:53 +0200 -Subject: [thermal-next PATCH v2 1/2] thermal: qcom: tsens: init debugfs only with +From de48d8766afcd97d147699aaff78a338081c9973 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 22 Oct 2022 14:56:55 +0200 +Subject: [PATCH 1/3] thermal/drivers/qcom/tsens: Init debugfs only with successful probe -calibrate and tsens_register can fail or PROBE_DEFER. This will cause a +Calibrate and tsens_register can fail or PROBE_DEFER. This will cause a double or a wrong init of the debugfs information. Init debugfs only with successful probe fixing warning about directory already present. -Signed-off-by: Ansuel Smith +Signed-off-by: Christian Marangi Acked-by: Thara Gopinath +Link: https://lore.kernel.org/r/20221022125657.22530-2-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano --- - drivers/thermal/qcom/tsens.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) + drivers/thermal/qcom/tsens.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -25,13 +27,12 @@ Acked-by: Thara Gopinath err_put_device: put_device(&op->dev); return ret; -@@ -1156,7 +1154,12 @@ static int tsens_probe(struct platform_d +@@ -1156,7 +1154,11 @@ static int tsens_probe(struct platform_d } } - return tsens_register(priv); + ret = tsens_register(priv); -+ + if (!ret) + tsens_debug_init(pdev); + diff --git a/target/linux/ipq806x/patches-6.1/004-v6.2-02-thermal-drivers-qcom-tsens-Fix-wrong-version-id-dbg_.patch b/target/linux/ipq806x/patches-6.1/004-v6.2-02-thermal-drivers-qcom-tsens-Fix-wrong-version-id-dbg_.patch new file mode 100644 index 0000000000..10f1e36b58 --- /dev/null +++ b/target/linux/ipq806x/patches-6.1/004-v6.2-02-thermal-drivers-qcom-tsens-Fix-wrong-version-id-dbg_.patch @@ -0,0 +1,29 @@ +From c7e077e921fa94e0c06c8d14af6c0504c8a5f4bd Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 22 Oct 2022 14:56:56 +0200 +Subject: [PATCH 2/3] thermal/drivers/qcom/tsens: Fix wrong version id + dbg_version_show + +For VER_0 the version was incorrectly reported as 0.1.0. + +Fix that and correctly report the major version for this old tsens +revision. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20221022125657.22530-3-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/qcom/tsens.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -692,7 +692,7 @@ static int dbg_version_show(struct seq_f + return ret; + seq_printf(s, "%d.%d.%d\n", maj_ver, min_ver, step_ver); + } else { +- seq_puts(s, "0.1.0\n"); ++ seq_printf(s, "0.%d.0\n", priv->feat->ver_major); + } + + return 0; diff --git a/target/linux/ipq806x/patches-6.1/004-v6.2-03-thermal-drivers-qcom-tsens-Rework-debugfs-file-struc.patch b/target/linux/ipq806x/patches-6.1/004-v6.2-03-thermal-drivers-qcom-tsens-Rework-debugfs-file-struc.patch new file mode 100644 index 0000000000..63cce7974b --- /dev/null +++ b/target/linux/ipq806x/patches-6.1/004-v6.2-03-thermal-drivers-qcom-tsens-Rework-debugfs-file-struc.patch @@ -0,0 +1,54 @@ +From 89992d95ed1046338c7866ef7bbe6de543a2af91 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 22 Oct 2022 14:56:57 +0200 +Subject: [PATCH 3/3] thermal/drivers/qcom/tsens: Rework debugfs file structure + +The current tsens debugfs structure is composed by: +- a tsens dir in debugfs with a version file +- a directory for each tsens istance with sensors file to dump all the + sensors value. + +This works on the assumption that we have the same version for each +istance but this assumption seems fragile and with more than one tsens +istance results in the version file not tracking each of them. + +A better approach is to just create a subdirectory for each tsens +istance and put there version and sensors debugfs file. + +Using this new implementation results in less code since debugfs entry +are created only on successful tsens probe. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20221022125657.22530-4-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/qcom/tsens.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -704,21 +704,14 @@ DEFINE_SHOW_ATTRIBUTE(dbg_sensors); + static void tsens_debug_init(struct platform_device *pdev) + { + struct tsens_priv *priv = platform_get_drvdata(pdev); +- struct dentry *root, *file; + +- root = debugfs_lookup("tsens", NULL); +- if (!root) ++ priv->debug_root = debugfs_lookup("tsens", NULL); ++ if (!priv->debug_root) + priv->debug_root = debugfs_create_dir("tsens", NULL); +- else +- priv->debug_root = root; +- +- file = debugfs_lookup("version", priv->debug_root); +- if (!file) +- debugfs_create_file("version", 0444, priv->debug_root, +- pdev, &dbg_version_fops); + + /* A directory for each instance of the TSENS IP */ + priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root); ++ debugfs_create_file("version", 0444, priv->debug, pdev, &dbg_version_fops); + debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops); + } + #else diff --git a/target/linux/ipq806x/patches-6.1/110-02-thermal-qcom-tsens-simplify-debugfs-init-function.patch b/target/linux/ipq806x/patches-6.1/110-02-thermal-qcom-tsens-simplify-debugfs-init-function.patch deleted file mode 100644 index 0fbc4bd8ca..0000000000 --- a/target/linux/ipq806x/patches-6.1/110-02-thermal-qcom-tsens-simplify-debugfs-init-function.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 4204f22060f7a5d42c6ccb4d4c25a6a875571099 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Mon, 19 Apr 2021 03:08:37 +0200 -Subject: [thermal-next PATCH v2 2/2] thermal: qcom: tsens: simplify debugfs init - function - -Simplify debugfs init function. -- Add check for existing dev directory. -- Fix wrong version in dbg_version_show (with version 0.0.0, 0.1.0 was - incorrectly reported) - -Signed-off-by: Ansuel Smith -Reviewed-by: Thara Gopinath ---- - drivers/thermal/qcom/tsens.c | 16 +++++++--------- - 1 file changed, 7 insertions(+), 9 deletions(-) - ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -692,7 +692,7 @@ static int dbg_version_show(struct seq_f - return ret; - seq_printf(s, "%d.%d.%d\n", maj_ver, min_ver, step_ver); - } else { -- seq_puts(s, "0.1.0\n"); -+ seq_printf(s, "0.%d.0\n", priv->feat->ver_major); - } - - return 0; -@@ -704,21 +704,17 @@ DEFINE_SHOW_ATTRIBUTE(dbg_sensors); - static void tsens_debug_init(struct platform_device *pdev) - { - struct tsens_priv *priv = platform_get_drvdata(pdev); -- struct dentry *root, *file; - -- root = debugfs_lookup("tsens", NULL); -- if (!root) -+ priv->debug_root = debugfs_lookup("tsens", NULL); -+ if (!priv->debug_root) - priv->debug_root = debugfs_create_dir("tsens", NULL); -- else -- priv->debug_root = root; - -- file = debugfs_lookup("version", priv->debug_root); -- if (!file) -+ if (!debugfs_lookup("version", priv->debug_root)) - debugfs_create_file("version", 0444, priv->debug_root, - pdev, &dbg_version_fops); - - /* A directory for each instance of the TSENS IP */ -- priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root); -+ priv->debug = debugfs_lookup(dev_name(&pdev->dev), priv->debug_root); - debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops); - } - #else diff --git a/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch b/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch index 3a6c281793..45f05dd423 100644 --- a/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch +++ b/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch @@ -31,7 +31,7 @@ Signed-off-by: Christian Marangi }; opp_table_l2: opp_table_l2 { -@@ -1410,6 +1400,16 @@ +@@ -1409,6 +1399,16 @@ #reset-cells = <1>; }; diff --git a/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch b/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch index a324b6facf..24e0ecf619 100644 --- a/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch +++ b/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch @@ -32,7 +32,7 @@ Signed-off-by: Christian Marangi thermal-zones { sensor0-thermal { polling-delay-passive = <0>; -@@ -1410,6 +1422,13 @@ +@@ -1409,6 +1421,13 @@ operating-points-v2 = <&opp_table_l2>; }; diff --git a/target/linux/lantiq/patches-5.15/0321-MIPS-lantiq-register-smp_ops-on-non-smp-platforms.patch b/target/linux/lantiq/patches-5.15/0321-MIPS-lantiq-register-smp_ops-on-non-smp-platforms.patch new file mode 100644 index 0000000000..78043545b0 --- /dev/null +++ b/target/linux/lantiq/patches-5.15/0321-MIPS-lantiq-register-smp_ops-on-non-smp-platforms.patch @@ -0,0 +1,33 @@ +From 6e8d8b183accefae42c62f1bd495a405ce454c7d Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Sun, 21 Jan 2024 18:36:23 +0100 +Subject: [PATCH] MIPS: lantiq: register smp_ops on non-smp platforms + +Lantiq uses a common kernel config for devices with 24Kc and 34Kc cores. +The changes made previously to add support for interrupts on all cores +work on 24Kc platforms with SMP disabled and 34Kc platforms with SMP +enabled. This patch fixes boot issues on Danube (single core 24Kc) with +SMP enabled. + +Fixes: 730320fd770d ("MIPS: lantiq: enable all hardware interrupts on second VPE") +Signed-off-by: Aleksander Jan Bajkowski +--- + arch/mips/lantiq/prom.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/arch/mips/lantiq/prom.c ++++ b/arch/mips/lantiq/prom.c +@@ -123,10 +123,9 @@ void __init prom_init(void) + prom_init_cmdline(); + + #if defined(CONFIG_MIPS_MT_SMP) +- if (cpu_has_mipsmt) { +- lantiq_smp_ops = vsmp_smp_ops; ++ lantiq_smp_ops = vsmp_smp_ops; ++ if (cpu_has_mipsmt) + lantiq_smp_ops.init_secondary = lantiq_init_secondary; +- register_smp_ops(&lantiq_smp_ops); +- } ++ register_smp_ops(&lantiq_smp_ops); + #endif + } diff --git a/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch index 46c304032d..f1ce7cc0ad 100644 --- a/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ b/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -11,9 +11,19 @@ Signed-off-by: Bhaskar Upadhaya include/linux/phy.h | 3 +++ 1 file changed, 3 insertions(+) +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -136,6 +136,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_RXAUI: + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_1000BASEKX: ++ case PHY_INTERFACE_MODE_2500SGMII: + return 1; + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -398,6 +398,7 @@ void phylink_get_linkmodes(unsigned long +@@ -400,6 +400,7 @@ void phylink_get_linkmodes(unsigned long caps |= MAC_1000FD; break; @@ -21,7 +31,7 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_2500BASEX: caps |= MAC_2500FD; break; -@@ -651,6 +652,10 @@ static int phylink_parse_mode(struct phy +@@ -654,6 +655,10 @@ static int phylink_parse_mode(struct phy phylink_set(pl->supported, 2500baseX_Full); break; @@ -34,18 +44,18 @@ Signed-off-by: Bhaskar Upadhaya break; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -153,6 +153,7 @@ typedef enum { - PHY_INTERFACE_MODE_USXGMII, - /* 10GBASE-KR - with Clause 73 AN */ +@@ -157,6 +157,7 @@ typedef enum { PHY_INTERFACE_MODE_10GKR, + PHY_INTERFACE_MODE_QUSGMII, + PHY_INTERFACE_MODE_1000BASEKX, + PHY_INTERFACE_MODE_2500SGMII, PHY_INTERFACE_MODE_MAX, } phy_interface_t; -@@ -268,6 +269,8 @@ static inline const char *phy_modes(phy_ - return "10gbase-kr"; - case PHY_INTERFACE_MODE_100BASEX: +@@ -276,6 +277,8 @@ static inline const char *phy_modes(phy_ return "100base-x"; + case PHY_INTERFACE_MODE_QUSGMII: + return "qusgmii"; + case PHY_INTERFACE_MODE_2500SGMII: + return "sgmii-2500"; default: diff --git a/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch index 77c9764078..6af915da90 100644 --- a/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ b/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -25,7 +25,7 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_QUSGMII: --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -199,6 +199,7 @@ static int phylink_interface_max_speed(p +@@ -200,6 +200,7 @@ static int phylink_interface_max_speed(p return SPEED_1000; case PHY_INTERFACE_MODE_2500BASEX: @@ -35,7 +35,7 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_5GBASER: --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -157,6 +157,7 @@ typedef enum { +@@ -159,6 +159,7 @@ typedef enum { PHY_INTERFACE_MODE_10GKR, PHY_INTERFACE_MODE_QUSGMII, PHY_INTERFACE_MODE_1000BASEKX, @@ -43,7 +43,7 @@ Signed-off-by: Bhaskar Upadhaya PHY_INTERFACE_MODE_MAX, } phy_interface_t; -@@ -276,6 +277,8 @@ static inline const char *phy_modes(phy_ +@@ -280,6 +281,8 @@ static inline const char *phy_modes(phy_ return "100base-x"; case PHY_INTERFACE_MODE_QUSGMII: return "qusgmii"; diff --git a/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch b/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch index f0d7100945..265756ea70 100644 --- a/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch +++ b/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch @@ -32,7 +32,7 @@ Signed-off-by: Ioana Ciornei --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -485,6 +485,7 @@ unsigned long phylink_get_capabilities(p +@@ -487,6 +487,7 @@ unsigned long phylink_get_capabilities(p break; case PHY_INTERFACE_MODE_2500BASEX: diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi new file mode 100644 index 0000000000..10cee7bcef --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7622.dtsi" +#include "mt6380.dtsi" +#include +#include + +/ { + aliases { + serial0 = &uart0; + label-mac-device = &gmac0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; + }; + + cpus { + cpu@0 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + + cpu@1 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + label = "reset"; + linux,code = ; + }; + + button-wps { + gpios = <&pio 102 GPIO_ACTIVE_LOW>; + label = "wps"; + linux,code = ; + }; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; +}; + +&bch { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + phy-mode = "2500base-x"; + reg = <0>; + nvmem-cells = <&macaddr_odm 1>; + nvmem-cell-names = "mac-address"; + fixed-link { + full-duplex; + pause; + speed = <2500>; + }; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + switch: switch@0 { + compatible = "mediatek,mt7531"; + reg = <0>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios = <&pio 54 0>; + + ports { + wan: port@4 { + reg = <4>; + label = "wan"; + nvmem-cells = <&macaddr_odm 0>; + nvmem-cell-names = "mac-address"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pio { + epa_elna_pins: epa-elna-pins { + mux { + function = "antsel"; + groups = "antsel0", "antsel1", "antsel2", "antsel3", + "antsel4", "antsel5", "antsel6", "antsel7", + "antsel8", "antsel9", "antsel12", "antsel13", + "antsel14", "antsel15", "antsel16", "antsel17"; + }; + }; + + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio", "rgmii_via_gmac2"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie0_pad_perst", + "pcie0_1_waken", + "pcie0_1_clkreq"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie1_pad_perst", + "pcie1_0_waken", + "pcie1_0_clkreq"; + }; + }; + + pmic_bus_pins: pmic-bus-pins { + mux { + function = "pmic"; + groups = "pmic_bus"; + }; + }; + + /* Serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_0_tx_rx"; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&pwrap { + pinctrl-names = "default"; + pinctrl-0 = <&pmic_bus_pins>; + status = "okay"; +}; + +&rtc { + status = "disabled"; +}; + +&sata { + status = "disabled"; +}; + +&sata_phy { + status = "disabled"; +}; + +&slot0 { + wmac1: mt7915@0,0 { + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + mediatek,mtd-eeprom = <&factory 0x05000>; + nvmem-cells = <&macaddr_odm 3>; + nvmem-cell-names = "mac-address"; + }; +}; + +&snfi { + pinctrl-names = "default"; + pinctrl-0 = <&serial_nand_pins>; + status = "okay"; + + snand: flash@0 { + compatible = "spi-nand"; + mediatek,bmt-table-size = <0x1000>; + mediatek,bmt-v2; + nand-ecc-engine = <&snfi>; + reg = <0>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Preloader"; + reg = <0x00000000 0x00080000>; + read-only; + }; + + partition@80000 { + label = "ATF"; + reg = <0x00080000 0x00040000>; + read-only; + }; + + partition@C0000 { + label = "Bootloader"; + reg = <0x000C0000 0x00080000>; + read-only; + }; + + partition@140000 { + label = "BootConfig"; + reg = <0x00140000 0x00040000>; + }; + + partition@180000 { + label = "Odm"; + reg = <0x00180000 0x00040000>; + read-only; + odm_partition: nvmem-layout { + compatible = "fixed-layout"; + }; + }; + + config1: partition@1C0000 { + compatible = "nvmem-cells"; + label = "Config1"; + reg = <0x001C0000 0x00080000>; + read-only; + }; + + partition@240000 { + label = "Config2"; + reg = <0x00240000 0x00080000>; + read-only; + }; + + partition@2C0000 { + label = "Kernel1"; + reg = <0x002C0000 0x02D00000>; + + compatible = "denx,fit"; + openwrt,cmdline-match = "boot_part=Kernel1"; + partition@0 { + label = "kernel"; + reg = <0x00000000 0x00800000>; + }; + + partition@800000 { + label = "ubi"; + reg = <0x00800000 0x02500000>; + }; + }; + + partition@2FC0000 { + label = "Kernel2"; + reg = <0x02FC0000 0x02D00000>; + + compatible = "denx,fit"; + openwrt,cmdline-match = "boot_part=Kernel2"; + partition@0 { + label = "kernel"; + reg = <0x00000000 0x00800000>; + }; + + partition@800000 { + label = "ubi"; + reg = <0x00800000 0x02500000>; + }; + }; + + factory: partition@5CC0000 { + label = "Factory"; + reg = <0x05CC0000 0x00100000>; + read-only; + }; + + partition@5DC0000 { + label = "Mydlink"; + reg = <0x05DC0000 0x00200000>; + read-only; + }; + + partition@5FC0000 { + label = "Storage"; + reg = <0x05FC0000 0x00300000>; + read-only; + }; + }; + }; +}; + +&ssusb { + status = "disabled"; +}; + +&u3phy { + status = "disabled"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; + +&wmac { + pinctrl-names = "default"; + pinctrl-0 = <&epa_elna_pins>; + mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&macaddr_odm 2>; + nvmem-cell-names = "mac-address"; + status = "okay"; +}; + diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts index 9c90cee516..2b40c5e7d5 100644 --- a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts @@ -1,401 +1,63 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include "mt7622.dtsi" -#include "mt6380.dtsi" -#include -#include +#include "mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi" +#include / { model = "D-Link EAGLE PRO AI M32 A1"; compatible = "dlink,eagle-pro-ai-m32-a1", "mediatek,mt7622"; aliases { - led-boot = &status_orange; - led-failsafe = &status_red; - led-running = &status_white; - led-upgrade = &status_red; - serial0 = &uart0; - label-mac-device = &gmac0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; - }; - - cpus { - cpu@0 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; - }; - - cpu@1 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - - reset { - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - label = "reset"; - linux,code = ; - }; - - wps { - gpios = <&pio 102 GPIO_ACTIVE_LOW>; - label = "wps"; - linux,code = ; - }; + led-boot = &led_status_orange; + led-failsafe = &led_status_red; + led-running = &led_status_white; + led-upgrade = &led_status_red; }; leds { compatible = "gpio-leds"; - status_white: status_white { - label = "white:status"; + led_status_white: led-status-white { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 85 GPIO_ACTIVE_LOW>; }; - status_orange: status_orange { - label = "orange:status"; + led_status_orange: led-status-orange { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 20 GPIO_ACTIVE_LOW>; default-state = "on"; }; - status_red: status_red { - label = "red:status"; + led_status_red: led-status-red { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 17 GPIO_ACTIVE_LOW>; }; }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; }; -&bch { - status = "okay"; -}; - -&btif { - status = "okay"; -}; - -ð { - pinctrl-names = "default"; - pinctrl-0 = <ð_pins>; - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - nvmem-cells = <&macaddr_odm_83>; - nvmem-cell-names = "mac-address"; - phy-mode = "2500base-x"; - reg = <0>; - - fixed-link { - full-duplex; - pause; - speed = <2500>; +&switch { + ports { + port@2 { + reg = <2>; + label = "lan2"; }; - }; - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - switch@0 { - compatible = "mediatek,mt7531"; - reg = <0>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - reset-gpios = <&pio 54 0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@2 { - reg = <2>; - label = "lan2"; - }; - - port@3 { - reg = <3>; - label = "lan1"; - }; - - wan: port@4 { - reg = <4>; - label = "wan"; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; + port@3 { + reg = <3>; + label = "lan1"; }; }; }; -&pcie0 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie0_pins>; - status = "okay"; -}; - -&pcie1 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie1_pins>; - status = "okay"; -}; - -&pio { - epa_elna_pins: epa-elna-pins { - mux { - function = "antsel"; - groups = "antsel0", "antsel1", "antsel2", "antsel3", - "antsel4", "antsel5", "antsel6", "antsel7", - "antsel8", "antsel9", "antsel12", "antsel13", - "antsel14", "antsel15", "antsel16", "antsel17"; - }; - }; - - eth_pins: eth-pins { - mux { - function = "eth"; - groups = "mdc_mdio", "rgmii_via_gmac2"; - }; - }; - - pcie0_pins: pcie0-pins { - mux { - function = "pcie"; - groups = "pcie0_pad_perst", - "pcie0_1_waken", - "pcie0_1_clkreq"; - }; - }; - - pcie1_pins: pcie1-pins { - mux { - function = "pcie"; - groups = "pcie1_pad_perst", - "pcie1_0_waken", - "pcie1_0_clkreq"; - }; - }; - - pmic_bus_pins: pmic-bus-pins { - mux { - function = "pmic"; - groups = "pmic_bus"; - }; - }; - - /* Serial NAND is shared pin with SPI-NOR */ - serial_nand_pins: serial-nand-pins { - mux { - function = "flash"; - groups = "snfi"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0_0_tx_rx"; - }; - }; - - watchdog_pins: watchdog-pins { - mux { - function = "watchdog"; - groups = "watchdog"; - }; +&odm_partition { + macaddr_odm: macaddr@83 { + compatible = "mac-base"; + reg = <0x83 0x6>; + #nvmem-cell-cells = <1>; }; }; -&pwrap { - pinctrl-names = "default"; - pinctrl-0 = <&pmic_bus_pins>; - status = "okay"; -}; - -&rtc { - status = "disabled"; -}; - -&sata { - status = "disabled"; -}; - -&sata_phy { - status = "disabled"; -}; - -&slot0 { - wmac1: mt7915@0,0 { - reg = <0x0000 0 0 0 0>; - ieee80211-freq-limit = <5000000 6000000>; - mediatek,mtd-eeprom = <&factory 0x05000>; - }; -}; - -&snfi { - pinctrl-names = "default"; - pinctrl-0 = <&serial_nand_pins>; - status = "okay"; - - snand: flash@0 { - compatible = "spi-nand"; - mediatek,bmt-table-size = <0x1000>; - mediatek,bmt-v2; - nand-ecc-engine = <&snfi>; - reg = <0>; - spi-rx-bus-width = <4>; - spi-tx-bus-width = <4>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "Preloader"; - reg = <0x00000000 0x00080000>; - read-only; - }; - - partition@80000 { - label = "ATF"; - reg = <0x00080000 0x00040000>; - read-only; - }; - - partition@C0000 { - label = "Bootloader"; - reg = <0x000C0000 0x00080000>; - read-only; - }; - - partition@140000 { - label = "BootConfig"; - reg = <0x00140000 0x00040000>; - read-only; - }; - - odm: partition@180000 { - label = "Odm"; - reg = <0x00180000 0x00040000>; - read-only; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_odm_83: macaddr@83 { - reg = <0x83 0x6>; - }; - }; - }; - - config1: partition@1C0000 { - label = "Config1"; - reg = <0x001C0000 0x00080000>; - read-only; - }; - - partition@240000 { - label = "Config2"; - reg = <0x00240000 0x00080000>; - read-only; - }; - - partition@2C0000 { - label = "Kernel1"; - reg = <0x002C0000 0x02D00000>; - - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - partition@0 { - label = "kernel"; - reg = <0x00000000 0x00800000>; - }; - - partition@800000 { - label = "ubi"; - reg = <0x00800000 0x02500000>; - }; - }; - - partition@2FC0000 { - label = "Kernel2"; - reg = <0x02FC0000 0x02D00000>; - read-only; - }; - - factory: partition@5CC0000 { - label = "Factory"; - reg = <0x05CC0000 0x00100000>; - read-only; - }; - - partition@5DC0000 { - label = "Mydlink"; - reg = <0x05DC0000 0x00200000>; - read-only; - }; - - partition@5FC0000 { - label = "Storage"; - reg = <0x05FC0000 0x00300000>; - read-only; - }; - }; - }; -}; - -&ssusb { - status = "disabled"; -}; - -&u3phy { - status = "disabled"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - status = "okay"; -}; - -&watchdog { - pinctrl-names = "default"; - pinctrl-0 = <&watchdog_pins>; - status = "okay"; -}; - -&wmac { - pinctrl-names = "default"; - pinctrl-0 = <&epa_elna_pins>; - mediatek,mtd-eeprom = <&factory 0x0000>; - status = "okay"; -}; - diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts new file mode 100644 index 0000000000..b21ba36cfc --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi" +#include + +/ { + model = "D-Link EAGLE PRO AI R32 A1"; + compatible = "dlink,eagle-pro-ai-r32-a1", "mediatek,mt7622"; + + aliases { + led-boot = &led_power_orange; + led-failsafe = &led_power_orange; + led-running = &led_power_white; + led-upgrade = &led_power_orange; + }; + + leds { + compatible = "gpio-leds"; + + led_power_orange: led-power-orange { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + }; + + led_power_white: led-power-white { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 85 GPIO_ACTIVE_LOW>; + }; + + led_internet_orange: led-internet-orange { + color = ; + function = "internet"; // LED_FUNCTION_INTERNET; + gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + led_internet_white: led-internet-white { + color = ; + function = "internet"; // LED_FUNCTION_INTERNET; + gpios = <&pio 17 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&switch { + ports { + port@0 { + reg = <0>; + label = "lan4"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + }; +}; + +&odm_partition { + macaddr_odm: macaddr@81 { + compatible = "mac-base"; + reg = <0x81 0x6>; + #nvmem-cell-cells = <1>; + }; +}; + diff --git a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi index abac02a72d..be216d972c 100644 --- a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi +++ b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi @@ -110,10 +110,6 @@ }; }; -&btif { - status = "okay"; -}; - &cir { pinctrl-names = "default"; pinctrl-0 = <&irrx_pins>; diff --git a/target/linux/mediatek/dts/mt7622-netgear-wax206.dts b/target/linux/mediatek/dts/mt7622-netgear-wax206.dts index 737ac35f3d..ce1cd46d2d 100644 --- a/target/linux/mediatek/dts/mt7622-netgear-wax206.dts +++ b/target/linux/mediatek/dts/mt7622-netgear-wax206.dts @@ -114,10 +114,6 @@ status = "okay"; }; -&btif { - status = "okay"; -}; - &cir { pinctrl-names = "default"; pinctrl-0 = <&irrx_pins>; diff --git a/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts b/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts index 4949cdb3d7..281c96e275 100644 --- a/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts +++ b/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts @@ -12,6 +12,7 @@ aliases { serial0 = &uart0; + label-mac-device = &gmac0; led-boot = &led_status_red; led-failsafe = &led_status_red; led-running = &led_status_green; @@ -65,7 +66,7 @@ reg = <0>; phy-mode = "2500base-x"; - nvmem-cells = <&macaddr_art_0>; + nvmem-cells = <&macaddr_art_0 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -134,7 +135,9 @@ #size-cells = <1>; macaddr_art_0: macaddr@0 { + compatible = "mac-base"; reg = <0x0 0x6>; + #nvmem-cell-cells = <1>; }; }; }; @@ -192,6 +195,8 @@ port@3 { reg = <3>; label = "wan"; + nvmem-cells = <&macaddr_art_0 3>; + nvmem-cell-names = "mac-address"; }; port@6 { diff --git a/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts b/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts index 520b8494ee..8f4dc23fb4 100644 --- a/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts +++ b/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts @@ -211,8 +211,8 @@ spi-cal-addrlen = <5>; spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; mediatek,nmbm; mediatek,bmt-max-ratio = <1>; mediatek,bmt-max-reserved-blocks = <64>; diff --git a/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts b/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts index e2fa8bf5d3..f4ba629525 100644 --- a/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts +++ b/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts @@ -10,7 +10,7 @@ aliases { ethernet0 = &gmac0; - label-mac-device = &lan1; + label-mac-device = &gmac0; led-boot = &led_status; led-failsafe = &led_status; led-running = &led_status; @@ -238,28 +238,19 @@ nvmem-cells = <&macaddr_bdinfo_de00 1>; }; - lan1: port@1 { + port@1 { reg = <1>; label = "lan1"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_bdinfo_de00 0>; }; port@2 { reg = <2>; label = "lan2"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_bdinfo_de00 0>; }; port@3 { reg = <3>; label = "lan3"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_bdinfo_de00 0>; }; port@6 { diff --git a/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts b/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts index 1dc4d380b8..dfe44843b9 100644 --- a/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts +++ b/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts @@ -160,8 +160,8 @@ reg = <0>; spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; spi-cal-enable; spi-cal-mode = "read-data"; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts new file mode 100644 index 0000000000..809e625ce1 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-ax3000t.dtsi" + +/ { + model = "Xiaomi Mi Router AX3000T (OpenWrt U-Boot layout)"; + compatible = "xiaomi,mi-router-ax3000t-ubootmod", "mediatek,mt7981"; +}; + +&partitions { + partition@600000 { + label = "ubi"; + reg = <0x600000 0x7000000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts new file mode 100644 index 0000000000..cc0d44fdf5 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-ax3000t.dtsi" + +/ { + model = "Xiaomi Mi Router AX3000T"; + compatible = "xiaomi,mi-router-ax3000t", "mediatek,mt7981"; +}; + +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&partitions { + // ubi_kernel is the ubi partition in stock. + partition@600000 { + label = "ubi_kernel"; + reg = <0x600000 0x2200000>; + }; + + /* ubi is the result of squashing + * consecutive stock partitions: + * - ubi1 + * - overlay + * - data + */ + partition@2800000 { + label = "ubi"; + reg = <0x2800000 0x4e00000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi new file mode 100644 index 0000000000..7b6fde8465 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-common.dtsi" + +&gmac0 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-2)>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; + + nfc@57 { + compatible = "nt082c"; + reg = <0x57>; + }; +}; + +&pio { + i2c_pins: i2c-pins { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi new file mode 100644 index 0000000000..d6872395a9 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include +#include + +#include "mt7981.dtsi" + +/ { + aliases { + serial0 = &uart0; + led-boot = &led_status_yellow; + led-failsafe = &led_status_yellow; + led-running = &led_status_blue; + led-upgrade = &led_status_yellow; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-mesh { + label = "mesh"; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + button-reset { + label = "reset"; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds: leds { + compatible = "gpio-leds"; + + led_status_blue: led-status-blue { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + led_status_yellow: led-status-yellow { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "wan"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00 0x100000>; + read-only; + }; + + partition@100000 { + label = "Nvram"; + reg = <0x100000 0x40000>; + }; + + partition@140000 { + label = "Bdata"; + reg = <0x140000 0x40000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "crash"; + reg = <0x580000 0x40000>; + read-only; + }; + + partition@5c0000 { + label = "crash_log"; + reg = <0x5c0000 0x40000>; + read-only; + }; + + partition@7600000 { + label = "KF"; + reg = <0x7600000 0x40000>; + read-only; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts deleted file mode 100644 index 7244cdfd61..0000000000 --- a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7981b-xiaomi-mi-router-wr30u.dtsi" - -/ { - model = "Xiaomi Mi Router WR30U (112M UBI with NMBM-Enabled layout)"; - compatible = "xiaomi,mi-router-wr30u-112m-nmbm", "mediatek,mt7981"; -}; - -&spi_nand { - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; -}; - -&partitions { - partition@600000 { - label = "ubi"; - reg = <0x600000 0x7000000>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi index 1e738a4474..87a2493a23 100644 --- a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi @@ -1,252 +1,23 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include -#include +#include "mt7981b-xiaomi-mi-router-common.dtsi" -#include "mt7981.dtsi" - -/ { - aliases { - serial0 = &uart0; - led-boot = &led_system_yellow; - led-failsafe = &led_system_yellow; - led-running = &led_system_blue; - led-upgrade = &led_system_yellow; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory { - reg = <0 0x40000000 0 0x10000000>; - }; - - gpio-keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&pio 1 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - mesh { - label = "mesh"; - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - linux,code = ; - linux,input-type = ; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_system_blue: system_blue { - label = "blue:system"; - gpios = <&pio 9 GPIO_ACTIVE_LOW>; - }; - - led_system_yellow: system_yellow { - label = "yellow:system"; - gpios = <&pio 10 GPIO_ACTIVE_LOW>; - }; - - led_network_blue { - label = "blue:network"; - gpios = <&pio 11 GPIO_ACTIVE_LOW>; - }; - - led_network_yellow { - label = "yellow:network"; - gpios = <&pio 12 GPIO_ACTIVE_LOW>; - }; - }; +&gmac0 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-1)>; }; -ð { - status = "okay"; +&leds { + led-wan-blue { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - nvmem-cells = <&macaddr_factory_4 (-1)>; - nvmem-cell-names = "mac-address"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; + led-wan-yellow { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; }; }; - -&mdio_bus { - switch: switch@1f { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; - }; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "wan"; - }; - - port@1 { - reg = <1>; - label = "lan2"; - }; - - port@2 { - reg = <2>; - label = "lan3"; - }; - - port@3 { - reg = <3>; - label = "lan4"; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_flash_pins>; - status = "okay"; - - spi_nand: flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spi-nand"; - reg = <0>; - - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - partitions: partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x00 0x100000>; - read-only; - }; - - partition@100000 { - label = "Nvram"; - reg = <0x100000 0x40000>; - }; - - partition@140000 { - label = "Bdata"; - reg = <0x140000 0x40000>; - }; - - factory: partition@180000 { - label = "Factory"; - reg = <0x180000 0x200000>; - read-only; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_4: macaddr@4 { - compatible = "mac-base"; - reg = <0x4 0x6>; - #nvmem-cell-cells = <1>; - }; - }; - }; - - partition@380000 { - label = "FIP"; - reg = <0x380000 0x200000>; - read-only; - }; - - partition@580000 { - label = "crash"; - reg = <0x580000 0x40000>; - read-only; - }; - - partition@5c0000 { - label = "crash_log"; - reg = <0x5c0000 0x40000>; - read-only; - }; - - partition@7600000 { - label = "KF"; - reg = <0x7600000 0x40000>; - read-only; - }; - }; - }; -}; - -&pio { - spi0_flash_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - - conf-pu { - pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = ; - bias-pull-up = ; - }; - - conf-pd { - pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = ; - bias-pull-down = ; - }; - }; -}; - -&wifi { - status = "okay"; - - mediatek,mtd-eeprom = <&factory 0x0>; -}; - -&uart0 { - status = "okay"; -}; - -&watchdog { - status = "okay"; -}; diff --git a/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts new file mode 100644 index 0000000000..4e6e834276 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + compatible = "yuncore,ax835", "mediatek,mt7981"; + model = "YunCore AX835"; + + aliases { + ethernet0 = &gmac0; + led-boot = &led_system; + led-failsafe = &led_system; + led-running = &led_system; + led-upgrade = &led_system; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + reg_led_vbus { + compatible = "regulator-fixed"; + regulator-name = "led_vbus"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + gpio = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + leds { + compatible = "gpio-leds"; + + led_system: led_system { + label = "red:system"; + gpios = <&pio 4 GPIO_ACTIVE_LOW>; + }; + + led_wifi24 { + label = "green:wifi2"; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led_wifi5 { + label = "blue:wifi5"; + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led_hwwatchdog { + // a gpio-wdt watchdog couldn't be made to work. + // the device rebooted after 5 minutes. + label = "hwwatchdog"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "timer"; + led-pattern = <1000>, <1000>; + }; + + // there's another "syswatchdog" on gpio2 + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_2a>; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "disabled"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory: partition@50000 { + label = "Factory"; + reg = <0x50000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + + macaddr_factory_24: macaddr@24 { + reg = <0x24 0x6>; + }; + + macaddr_factory_2a: macaddr@2a { + reg = <0x2a 0x6>; + }; + }; + }; + + partition@100000 { + label = "FIP"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0xe00000>; + }; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@3 { + reg = <3>; + label = "lan"; + }; + + port@4 { + reg = <4>; + label = "wan"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory 0>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts b/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts index 15cd69aaae..e2acb63771 100644 --- a/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts +++ b/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts @@ -213,8 +213,8 @@ reg = <0>; spi-max-frequency = <20000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; partitions: partitions { compatible = "fixed-partitions"; diff --git a/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts index 41e6d2471d..b05dec93b4 100644 --- a/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts +++ b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts @@ -131,6 +131,7 @@ compatible = "ethernet-phy-ieee802.3-c45"; reg = <5>; + mxl,led-drive-vdd; mxl,led-config = <0x03f0 0x0 0x0 0x0>; }; diff --git a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts index fded507039..26996e7b4a 100644 --- a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts +++ b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts @@ -13,6 +13,10 @@ aliases { serial0 = &uart0; + led-boot = &led_blue; + led-failsafe = &led_blue; + led-running = &led_white; + led-upgrade = &led_white; }; chosen { @@ -51,13 +55,12 @@ leds { compatible = "gpio-leds"; - led_run: led@0 { + led_blue: led@0 { label = "blue:run"; gpios = <&pio 38 GPIO_ACTIVE_LOW>; - default-state = "on"; }; - led@1 { + led_white: led@1 { label = "white:system"; gpios = <&pio 37 GPIO_ACTIVE_LOW>; }; diff --git a/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts b/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts new file mode 100644 index 0000000000..b62c2f4215 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Tianling Shen + */ + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + model = "JDCloud RE-CP-03"; + compatible = "jdcloud,re-cp-03", "mediatek,mt7986a"; + + aliases { + led-boot = &red_led; + led-failsafe = &red_led; + led-running = &green_led; + led-upgrade = &green_led; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + reg = <0 0x40000000 0 0x40000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-joylink { + label = "joylink"; + linux,code = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 7 GPIO_ACTIVE_HIGH>; + }; + + red_led: led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 11 GPIO_ACTIVE_HIGH>; + }; + + green_led: led-2 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy-handle = <&phy6>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + realtek,aldps-enable; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&mmc0 { + bus-width = <8>; + cap-mmc-highspeed; + hs400-ds-delay = <0x14014>; + max-frequency = <200000000>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + no-sd; + no-sdio; + non-removable; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + status = "okay"; +}; + +&pio { + mmc0_pins_default: mmc0-pins-default { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + wf_2g_5g_pins: wf-2g-5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@4 { + reg = <4>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + pinctrl-names = "default"; + pinctrl-0 = <&wf_2g_5g_pins>; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts b/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts index 42250be19a..f0a995820e 100644 --- a/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts +++ b/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts @@ -3,6 +3,7 @@ /dts-v1/; #include #include +#include #include "mt7986b.dtsi" @@ -41,34 +42,43 @@ compatible = "gpio-leds"; led-0 { - label = "green:lan2"; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; gpios = <&pio 7 GPIO_ACTIVE_LOW>; }; led-1 { - label = "green:lan1"; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; gpios = <&pio 9 GPIO_ACTIVE_LOW>; }; led-2 { - label = "green:lan0"; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <0>; gpios = <&pio 12 GPIO_ACTIVE_LOW>; }; led-3 { - label = "green:wan"; + color = ; + function = LED_FUNCTION_WAN; gpios = <&pio 13 GPIO_ACTIVE_LOW>; }; led-4 { - label = "orange:status"; + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 16 GPIO_ACTIVE_HIGH>; + panic-indicator; }; led_status_green: led-5 { - label = "green:status"; + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 17 GPIO_ACTIVE_HIGH>; - panic-indicator; }; }; }; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds index 360bdea9c8..b9fac1bebf 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds @@ -16,9 +16,9 @@ cudy,wr3000-v1) ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" ;; mercusys,mr90x-v1) - ucidef_set_led_netdev "lan0" "lan0" "green:lan0" "lan0" "link tx rx" - ucidef_set_led_netdev "lan1" "lan2" "green:lan1" "lan1" "link tx rx" - ucidef_set_led_netdev "lan2" "lan2" "green:lan2" "lan2" "link tx rx" + ucidef_set_led_netdev "lan-0" "lan-0" "green:lan-0" "lan0" "link tx rx" + ucidef_set_led_netdev "lan-1" "lan-1" "green:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan-2" "lan-2" "green:lan-2" "lan2" "link tx rx" ucidef_set_led_netdev "wan" "wan" "green:wan" "eth1" "link tx rx" ;; netgear,wax220) @@ -33,10 +33,9 @@ routerich,ax3000) ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" ucidef_set_led_netdev "wan-off" "wan-off" "red:wan" "wan" "link" ;; -xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod) - ucidef_set_led_netdev "wan" "wan" "blue:network" "wan" + ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" ;; xiaomi,redmi-router-ax6000-stock|\ xiaomi,redmi-router-ax6000-ubootmod) diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index a36d998a40..a198fb98c9 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -24,6 +24,7 @@ mediatek_setup_interfaces() ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" wan ;; asus,tuf-ax4200|\ + jdcloud,re-cp-03|\ mediatek,mt7981-rfb|\ zbtlink,zbt-z8102ax) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" eth1 @@ -66,13 +67,15 @@ mediatek_setup_interfaces() ucidef_set_interface_lan "eth0" ;; smartrg,sdg-8622|\ - smartrg,sdg-8632) + smartrg,sdg-8632|\ + yuncore,ax835) ucidef_set_interfaces_lan_wan lan wan ;; tplink,tl-xdr6086) ucidef_set_interfaces_lan_wan "lan1 lan2" eth1 ;; - xiaomi,mi-router-wr30u-112m-nmbm|\ + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-stock|\ @@ -108,11 +111,6 @@ mediatek_setup_macs() bananapi,bpi-r3) wan_mac=$(macaddr_add $(cat /sys/class/net/eth0/address) 1) ;; - cetron,ct3003) - lan_mac=$(mtd_get_mac_binary "art" 0) - wan_mac=$(macaddr_add "$lan_mac" 3) - label_mac=$lan_mac - ;; cmcc,rax3000m) case "$(cmdline_get_var root)" in /dev/mmc*) @@ -137,6 +135,11 @@ mediatek_setup_macs() lan_mac=$(macaddr_add "$wan_mac" 1) label_mac=$wan_mac ;; + jdcloud,re-cp-03) + wan_mac=$(mmc_get_mac_binary factory 0x2a) + lan_mac=$(mmc_get_mac_binary factory 0x24) + label_mac=$lan_mac + ;; mercusys,mr90x-v1) label_mac=$(get_mac_binary "/tmp/tp_data/default-mac" 0) lan_mac=$label_mac @@ -158,7 +161,8 @@ mediatek_setup_macs() wan_mac=$label_mac lan_mac=$(macaddr_add "$label_mac" 1) ;; - xiaomi,mi-router-wr30u-112m-nmbm|\ + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-stock|\ @@ -166,6 +170,9 @@ mediatek_setup_macs() wan_mac=$(mtd_get_mac_ascii Bdata ethaddr_wan) label_mac=$wan_mac ;; + yuncore,ax835) + label_mac=$(mtd_get_mac_binary "Factory" 0x4) + ;; esac [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata index cbbf1871a5..22ab26608f 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata @@ -72,7 +72,8 @@ case "$FIRMWARE" in CI_UBIPART="UBI_DEV" caldata_extract_ubi "Factory" 0x0 0x1000 ;; - glinet,gl-mt6000) + glinet,gl-mt6000|\ + jdcloud,re-cp-03) caldata_extract_mmc "factory" 0x0 0x1000 ;; esac diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index 7f013732d3..937d39066c 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -37,9 +37,9 @@ case "$board" in [ "$PHYNBR" = "1" ] && echo "$addr" > /sys${DEVPATH}/macaddress ;; bananapi,bpi-r3) - addr=$(macaddr_add $(cat /sys/class/net/eth0/address) 2) - [ "$PHYNBR" = "0" ] && macaddr_unsetbit $addr 6 > /sys${DEVPATH}/macaddress - [ "$PHYNBR" = "1" ] && macaddr_setbit $addr 6 > /sys${DEVPATH}/macaddress + addr=$(cat /sys/class/net/eth0/address) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress ;; cetron,ct3003) addr=$(mtd_get_mac_binary "art" 0) @@ -80,6 +80,9 @@ case "$board" in # addresses on multiple VIFs with the other radio. Use label mac to set LA bit. [ "$PHYNBR" = "1" ] && macaddr_setbit_la $(get_mac_label) > /sys${DEVPATH}/macaddress ;; + jdcloud,re-cp-03) + [ "$PHYNBR" = "1" ] && mmc_get_mac_binary factory 0xa > /sys${DEVPATH}/macaddress + ;; mercusys,mr90x-v1) addr=$(get_mac_binary "/tmp/tp_data/default-mac" 0) [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 9600f8745f..97c09f35a8 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -49,6 +49,7 @@ xiaomi_initial_setup() local board=$(board_name) case "$board" in + xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-stock) fw_setenv mtdparts "nmbm0:1024k(bl2),256k(Nvram),256k(Bdata),2048k(factory),2048k(fip),256k(crash),256k(crash_log),34816k(ubi),34816k(ubi1),32768k(overlay),12288k(data),256k(KF)" ;; @@ -110,7 +111,8 @@ platform_do_upgrade() { ;; esac ;; - cudy,wr3000-v1) + cudy,wr3000-v1|\ + yuncore,ax835) default_do_upgrade "$1" ;; glinet,gl-mt2500|\ @@ -126,11 +128,16 @@ platform_do_upgrade() { tplink,tl-xdr4288|\ tplink,tl-xdr6086|\ tplink,tl-xdr6088|\ + xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-ubootmod) CI_KERNPART="fit" nand_do_upgrade "$1" ;; + jdcloud,re-cp-03) + CI_KERNPART="production" + emmc_do_upgrade "$1" + ;; mercusys,mr90x-v1) CI_UBIPART="ubi0" nand_do_upgrade "$1" @@ -140,6 +147,7 @@ platform_do_upgrade() { EMMC_ROOT_DEV="$(cmdline_get_var root)" emmc_do_upgrade "$1" ;; + xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,redmi-router-ax6000-stock) CI_KERN_UBIPART=ubi_kernel @@ -196,6 +204,7 @@ platform_copy_config() { acer,predator-w6|\ glinet,gl-mt2500|\ glinet,gl-mt6000|\ + jdcloud,re-cp-03|\ ubnt,unifi-6-plus) emmc_copy_config ;; @@ -211,6 +220,7 @@ platform_pre_upgrade() { asus,tuf-ax6000) asus_initial_setup ;; + xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,redmi-router-ax6000-stock) xiaomi_initial_setup diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 1499f79b9a..8ba0b0efe8 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -268,6 +268,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y @@ -370,7 +371,7 @@ CONFIG_RPS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_MT7622=y CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTL8367S_GSW=y +# CONFIG_RTL8367S_GSW is not set CONFIG_RWSEM_SPIN_ON_OWNER=y CONFIG_SCHED_MC=y CONFIG_SCSI=y diff --git a/target/linux/mediatek/filogic/config-6.1 b/target/linux/mediatek/filogic/config-6.1 index 9473967d00..1687aadbc1 100644 --- a/target/linux/mediatek/filogic/config-6.1 +++ b/target/linux/mediatek/filogic/config-6.1 @@ -95,6 +95,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_RMAP=y CONFIG_CPU_THERMAL=y CONFIG_CRC16=y +CONFIG_CRC_CCITT=y CONFIG_CRYPTO_AES_ARM64=y CONFIG_CRYPTO_AES_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y @@ -286,6 +287,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index 15951df1ec..c64a46fe24 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -450,6 +450,32 @@ define Device/jcg_q30-pro endef TARGET_DEVICES += jcg_q30-pro +define Device/jdcloud_re-cp-03 + DEVICE_VENDOR := JDCloud + DEVICE_MODEL := RE-CP-03 + DEVICE_DTS := mt7986a-jdcloud-re-cp-03 + DEVICE_DTS_DIR := ../dts + DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware \ + e2fsprogs f2fsck mkf2fs + KERNEL_LOADADDR := 0x44000000 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGES := sysupgrade.itb + IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | \ + pad-rootfs | append-metadata + ARTIFACTS :=gpt.bin preloader.bin bl31-uboot.fip + ARTIFACT/gpt.bin := mt798x-gpt emmc + ARTIFACT/preloader.bin := mt7986-bl2 emmc-ddr4 + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot jdcloud_re-cp-03 +endef +TARGET_DEVICES += jdcloud_re-cp-03 + define Device/mediatek_mt7981-rfb DEVICE_VENDOR := MediaTek DEVICE_MODEL := MT7981 rfb @@ -728,10 +754,10 @@ define Device/ubnt_unifi-6-plus endef TARGET_DEVICES += ubnt_unifi-6-plus -define Device/xiaomi_mi-router-wr30u-112m-nmbm +define Device/xiaomi_mi-router-ax3000t DEVICE_VENDOR := Xiaomi - DEVICE_MODEL := Mi Router WR30U (112M UBI with NMBM-Enabled layout) - DEVICE_DTS := mt7981b-xiaomi-mi-router-wr30u-112m-nmbm + DEVICE_MODEL := Mi Router AX3000T + DEVICE_DTS := mt7981b-xiaomi-mi-router-ax3000t DEVICE_DTS_DIR := ../dts UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k @@ -743,7 +769,35 @@ ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) endif IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef -TARGET_DEVICES += xiaomi_mi-router-wr30u-112m-nmbm +TARGET_DEVICES += xiaomi_mi-router-ax3000t + +define Device/xiaomi_mi-router-ax3000t-ubootmod + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := Mi Router AX3000T (OpenWrt U-Boot layout) + DEVICE_DTS := mt7981b-xiaomi-mi-router-ax3000t-ubootmod + DEVICE_DTS_DIR := ../dts + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot xiaomi_mi-router-ax3000t +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS += initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-recovery.itb | ubinize-kernel +endif +endef +TARGET_DEVICES += xiaomi_mi-router-ax3000t-ubootmod define Device/xiaomi_mi-router-wr30u-stock DEVICE_VENDOR := Xiaomi @@ -835,6 +889,25 @@ endif endef TARGET_DEVICES += xiaomi_redmi-router-ax6000-ubootmod +define Device/yuncore_ax835 + DEVICE_VENDOR := YunCore + DEVICE_MODEL := AX835 + DEVICE_DTS := mt7981b-yuncore-ax835 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + IMAGES := sysupgrade.bin + IMAGE_SIZE := 14336k + SUPPORTED_DEVICES += mediatek,mt7981-spim-nor-rfb + KERNEL := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | check-size | append-metadata + DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += yuncore_ax835 + + define Device/zbtlink_zbt-z8102ax DEVICE_VENDOR := Zbtlink DEVICE_MODEL := ZBT-Z8102AX diff --git a/target/linux/mediatek/image/mt7622.mk b/target/linux/mediatek/image/mt7622.mk index d0f5280dcf..7df5eade82 100644 --- a/target/linux/mediatek/image/mt7622.mk +++ b/target/linux/mediatek/image/mt7622.mk @@ -37,9 +37,15 @@ define Build/bl31-uboot cat $(STAGING_DIR_IMAGE)/mt7622_$1-u-boot.fip >> $@ endef -# Append header to a D-Link M32 Kernel 1 partition -define Build/m32-recovery-header-kernel1 - echo -en "DLK6E6010001\x00\x00\xCF\x33" > "$@.header" +# Append header to a D-Link M32/R32 Kernel 1 partition +define Build/m32-r32-recovery-header-kernel1 + $(eval header_start=$(word 1,$(1))) +# create $@.header without the checksum + echo -en "$(header_start)\x00\x00" > "$@.header" +# Calculate checksum over data area ($@) and append it to the header. +# The checksum is the 2byte-sum over the whole data area. +# Every overflow during the checksum calculation must increment the current checksum value by 1. + od -v -w2 -tu2 -An --endian little "$@" | awk '{ s+=$$1; } END { s%=65535; printf "%c%c",s%256,s/256; }' >> "$@.header" echo -en "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x8D\x57\x30\x0B" >> "$@.header" # Byte 0-3: Erase Start 0x002C0000 # Byte 4-7: Erase Length 0x02D00000 @@ -48,9 +54,11 @@ define Build/m32-recovery-header-kernel1 echo -en "\x00\x00\x2C\x00\x00\x00\xD0\x02\x00\x00\x2C\x00\x00\x00\xD0\x02" >> "$@.header" # Only zeros echo -en "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" >> "$@.header" -# Note: The last 2 bytes of the following line are the checksum of the header -# If any data in the header will be changed, the checksum must be re-calculated - echo -en "\x42\x48\x02\x00\x00\x00\x08\x00\x00\x00\x00\x00\x60\x6E\x68\x61" >> "$@.header" +# Last 16 bytes, but without checksum + echo -en "\x42\x48\x02\x00\x00\x00\x08\x00\x00\x00\x00\x00\x60\x6E" >> "$@.header" +# Calculate and append checksum: The checksum must be set so that the 2byte-sum of the whole header is 0. +# Every overflow during the checksum calculation must increment the current checksum value by 1. + od -v -w2 -tu2 -An --endian little "$@.header" | awk '{s+=65535-$$1;}END{s%=65535;printf "%c%c",s%256,s/256;}' >> "$@.header" cat "$@.header" "$@" > "$@.new" mv "$@.new" "$@" rm "$@.header" @@ -168,12 +176,10 @@ define Device/buffalo_wsr-3200ax4s endef TARGET_DEVICES += buffalo_wsr-3200ax4s -define Device/dlink_eagle-pro-ai-m32-a1 +define Device/dlink_eagle-pro-ai-ax3200-a1 IMAGE_SIZE := 46080k DEVICE_VENDOR := D-Link - DEVICE_MODEL := EAGLE PRO AI M32 DEVICE_VARIANT := A1 - DEVICE_DTS := mt7622-dlink-eagle-pro-ai-m32-a1 DEVICE_DTS_DIR := ../dts DEVICE_PACKAGES := kmod-mt7915-firmware KERNEL_SIZE := 8192k @@ -183,10 +189,24 @@ define Device/dlink_eagle-pro-ai-m32-a1 IMAGES += tftp.bin recovery.bin IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata IMAGE/tftp.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | check-size - IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | m32-recovery-header-kernel1 +endef + +define Device/dlink_eagle-pro-ai-m32-a1 + $(Device/dlink_eagle-pro-ai-ax3200-a1) + DEVICE_MODEL := EAGLE PRO AI M32 + DEVICE_DTS := mt7622-dlink-eagle-pro-ai-m32-a1 + IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | m32-r32-recovery-header-kernel1 DLK6E6010001 endef TARGET_DEVICES += dlink_eagle-pro-ai-m32-a1 +define Device/dlink_eagle-pro-ai-r32-a1 + $(Device/dlink_eagle-pro-ai-ax3200-a1) + DEVICE_MODEL := EAGLE PRO AI R32 + DEVICE_DTS := mt7622-dlink-eagle-pro-ai-r32-a1 + IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | m32-r32-recovery-header-kernel1 DLK6E6015001 +endef +TARGET_DEVICES += dlink_eagle-pro-ai-r32-a1 + define Device/elecom_wrc-2533gent DEVICE_VENDOR := Elecom DEVICE_MODEL := WRC-2533GENT @@ -332,7 +352,7 @@ define Device/totolink_a8000ru DEVICE_MODEL := A8000RU DEVICE_DTS := mt7622-totolink-a8000ru DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7615-firmware swconfig + DEVICE_PACKAGES := kmod-mt7615-firmware kmod-usb3 swconfig IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef TARGET_DEVICES += totolink_a8000ru diff --git a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network index 75c5e37be1..6c43e46222 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network @@ -10,6 +10,7 @@ mediatek_setup_interfaces() case $board in bananapi,bpi-r64|\ buffalo,wsr-3200ax4s|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ linksys,e8450|\ linksys,e8450-ubi|\ @@ -64,10 +65,6 @@ mediatek_setup_macs() wan_mac=$lan_mac label_mac=$lan_mac ;; - dlink,eagle-pro-ai-m32-a1) - wan_mac=$(get_mac_label) - lan_mac=$(macaddr_add $(get_mac_label) 1) - ;; reyee,ax3200-e5|\ ruijie,rg-ew3200gx-pro) lan_mac=$(macaddr_add $(get_mac_label) 1) diff --git a/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index e9cc592237..7ee9f24071 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -18,10 +18,6 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_add $basemac 1 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $basemac 8 > /sys${DEVPATH}/macaddress ;; - dlink,eagle-pro-ai-m32-a1) - [ "$PHYNBR" = "0" ] && macaddr_add $(cat /sys/class/net/eth0/address) 2 > /sys${DEVPATH}/macaddress - [ "$PHYNBR" = "1" ] && macaddr_add $(cat /sys/class/net/eth0/address) 3 > /sys${DEVPATH}/macaddress - ;; reyee,ax3200-e5|\ ruijie,rg-ew3200gx-pro) [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 3 > /sys${DEVPATH}/macaddress diff --git a/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount b/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount index bc4eeb6530..19a321b48b 100755 --- a/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount +++ b/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount @@ -4,6 +4,14 @@ START=99 boot() { case $(board_name) in + dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1) + if grep -q boot_part=Kernel1 /proc/cmdline; then + fw_setenv boot_part 1 + else + fw_setenv boot_part 2 + fi + ;; linksys,e8450) mtd erase senv || true ;; diff --git a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh index e256d2b533..3a2d7a4cd6 100755 --- a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh @@ -35,6 +35,7 @@ platform_do_upgrade() { fi ;; dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ mediatek,mt7622-rfb1-ubi|\ netgear,wax206|\ @@ -73,7 +74,8 @@ platform_check_image() { buffalo,wsr-3200ax4s) buffalo_check_image "$board" "$magic" "$1" || return 1 ;; - dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ mediatek,mt7622-rfb1-ubi|\ netgear,wax206|\ diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 18f972e949..7bca33c0ae 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -8,7 +8,6 @@ CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y CONFIG_ARCH_MMAP_RND_BITS=18 CONFIG_ARCH_MMAP_RND_BITS_MAX=24 CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 CONFIG_ARCH_PROC_KCORE_TEXT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -17,10 +16,8 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_WANTS_NO_INSTR=y CONFIG_ARM64=y CONFIG_ARM64_4K_PAGES=y -# CONFIG_ARM64_CNP is not set CONFIG_ARM64_CRYPTO=y CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_ERRATUM_845719=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PA_BITS=48 @@ -28,7 +25,6 @@ CONFIG_ARM64_PA_BITS_48=y CONFIG_ARM64_TAGGED_ADDR_ABI=y CONFIG_ARM64_VA_BITS=39 CONFIG_ARM64_VA_BITS_39=y -# CONFIG_ARMV8_DEPRECATED is not set CONFIG_ARM_AMBA=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y @@ -46,9 +42,9 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_MQ_PCI=y CONFIG_BLK_PM=y -CONFIG_BLOCK_COMPAT=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y @@ -74,19 +70,7 @@ CONFIG_COMMON_CLK_MT7622_HIFSYS=y # CONFIG_COMMON_CLK_MT7988 is not set # CONFIG_COMMON_CLK_MT8173 is not set # CONFIG_COMMON_CLK_MT8183 is not set -# CONFIG_COMMON_CLK_MT8183_AUDIOSYS is not set -# CONFIG_COMMON_CLK_MT8183_CAMSYS is not set -# CONFIG_COMMON_CLK_MT8183_IMGSYS is not set -# CONFIG_COMMON_CLK_MT8183_IPU_ADL is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CONN is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CORE0 is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CORE1 is not set -# CONFIG_COMMON_CLK_MT8183_MFGCFG is not set -# CONFIG_COMMON_CLK_MT8183_MMSYS is not set -# CONFIG_COMMON_CLK_MT8183_VDECSYS is not set -# CONFIG_COMMON_CLK_MT8183_VENCSYS is not set # CONFIG_COMMON_CLK_MT8516 is not set -# CONFIG_COMMON_CLK_MT8516_AUDSYS is not set CONFIG_COMPAT_32BIT_TIME=y CONFIG_CONFIGFS_FS=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 @@ -144,7 +128,6 @@ CONFIG_DIMLIB=y CONFIG_DMADEVICES=y CONFIG_DMA_DIRECT_REMAP=y CONFIG_DMA_ENGINE=y -CONFIG_DMA_ENGINE_RAID=y CONFIG_DMA_OF=y CONFIG_DMA_REMAP=y CONFIG_DMA_VIRTUAL_CHANNELS=y @@ -254,8 +237,8 @@ CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_SPLIT_FIT_FW=y CONFIG_MTD_UBI=y CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_FASTMAP=y CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_FASTMAP=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 # CONFIG_MTK_CMDQ is not set # CONFIG_MTK_CQDMA is not set @@ -288,6 +271,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=2 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y @@ -301,8 +285,9 @@ CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OF_OVERLAY=y CONFIG_OF_RESOLVE=y -CONFIG_OLD_SIGSUSPEND3=y CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y CONFIG_PARTITION_PERCPU=y CONFIG_PCI=y CONFIG_PCIEAER=y @@ -319,6 +304,7 @@ CONFIG_PCI_DOMAINS=y CONFIG_PCI_DOMAINS_GENERIC=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCS_MTK_LYNXI=y CONFIG_PERF_EVENTS=y CONFIG_PGTABLE_LEVELS=3 CONFIG_PHYLIB=y @@ -420,7 +406,6 @@ CONFIG_SWCONFIG=y CONFIG_SWIOTLB=y CONFIG_SWPHY=y CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYSVIPC_COMPAT=y CONFIG_THERMAL=y CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 @@ -435,6 +420,7 @@ CONFIG_THREAD_INFO_IN_TASK=y CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TIMER_OF=y CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y CONFIG_TREE_RCU=y CONFIG_TREE_SRCU=y CONFIG_UBIFS_FS=y diff --git a/target/linux/mediatek/mt7622/config-6.1 b/target/linux/mediatek/mt7622/config-6.1 index 6272a3bac6..89260f78ee 100644 --- a/target/linux/mediatek/mt7622/config-6.1 +++ b/target/linux/mediatek/mt7622/config-6.1 @@ -4,7 +4,6 @@ CONFIG_AQUANTIA_PHY=y CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_FORCE_MAX_ORDER=11 CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MEDIATEK=y CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y @@ -104,6 +103,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_RMAP=y CONFIG_CPU_THERMAL=y CONFIG_CRC16=y +CONFIG_CRC_CCITT=y CONFIG_CRYPTO_AES_ARM64=y CONFIG_CRYPTO_AES_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y @@ -155,7 +155,6 @@ CONFIG_FIT_PARTITION=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y CONFIG_FRAME_POINTER=y -CONFIG_FRAME_WARN=2048 CONFIG_FS_IOMAP=y CONFIG_FS_MBCACHE=y CONFIG_FWNODE_MDIO=y @@ -291,6 +290,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=2 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y diff --git a/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch index 4c980e9438..e795eda3b2 100644 --- a/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ b/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -1234,6 +1234,70 @@ static int spi_transfer_wait(struct spi_ +@@ -1246,6 +1246,70 @@ static int spi_transfer_wait(struct spi_ return 0; } @@ -82,7 +82,7 @@ Signed-off-by: SkyLake.Huang static void _spi_transfer_delay_ns(u32 ns) { if (!ns) -@@ -2021,6 +2085,75 @@ void spi_flush_queue(struct spi_controll +@@ -2033,6 +2097,75 @@ void spi_flush_queue(struct spi_controll /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OF) @@ -158,7 +158,7 @@ Signed-off-by: SkyLake.Huang static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, struct device_node *nc) { -@@ -2139,6 +2272,10 @@ of_register_spi_device(struct spi_contro +@@ -2151,6 +2284,10 @@ of_register_spi_device(struct spi_contro if (rc) goto err_out; diff --git a/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch index b8964f4e76..977bdeb5b1 100644 --- a/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch +++ b/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -367,6 +367,12 @@ config ROCKCHIP_PHY +@@ -364,6 +364,12 @@ config ROCKCHIP_PHY help Currently supports the integrated Ethernet PHY. @@ -15,7 +15,7 @@ help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -95,6 +95,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o +@@ -91,6 +91,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch index 9da2975582..72ad2a9846 100644 --- a/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ b/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -42,7 +42,7 @@ Signed-off-by: David S. Miller L: linux-i2c@vger.kernel.org --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -293,6 +293,18 @@ config MEDIATEK_GE_PHY +@@ -290,6 +290,18 @@ config MEDIATEK_GE_PHY help Supports the MediaTek Gigabit Ethernet PHYs. @@ -63,7 +63,7 @@ Signed-off-by: David S. Miller help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -81,6 +81,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o +@@ -77,6 +77,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o diff --git a/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch index 7151eb35cc..7600819246 100644 --- a/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch +++ b/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -305,6 +305,13 @@ config MEDIATEK_GE_SOC_PHY +@@ -302,6 +302,13 @@ config MEDIATEK_GE_SOC_PHY present in the SoCs efuse and will dynamically calibrate VCM (common-mode voltage) during startup. @@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -80,6 +80,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell +@@ -76,6 +76,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o diff --git a/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch b/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch index 69f2d2a545..d5c8a4e300 100644 --- a/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch +++ b/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch @@ -72,7 +72,7 @@ Signed-off-by: Wolfram Sang idev->adapter.dev.parent = &pdev->dev; --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -1028,7 +1028,7 @@ static int aspeed_i2c_probe_bus(struct p +@@ -1044,7 +1044,7 @@ static int aspeed_i2c_probe_bus(struct p bus->adap.algo = &aspeed_i2c_algo; bus->adap.dev.parent = &pdev->dev; bus->adap.dev.of_node = pdev->dev.of_node; diff --git a/target/linux/mediatek/patches-5.15/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch b/target/linux/mediatek/patches-5.15/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch new file mode 100644 index 0000000000..b0c20ab545 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch @@ -0,0 +1,599 @@ +From: Lorenzo Bianconi +Date: Thu, 2 Nov 2023 16:47:07 +0100 +Subject: [PATCH net-next 1/2] net: ethernet: mediatek: split tx and rx fields + in mtk_soc_data struct + +Split tx and rx fields in mtk_soc_data struct. This is a preliminary +patch to roll back to QDMA for MT7986 SoC in order to fix a hw hang +if the device receives a corrupted packet. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 210 ++++++++++++-------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 29 +-- + 2 files changed, 139 insertions(+), 100 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1239,7 +1239,7 @@ static int mtk_init_fq_dma(struct mtk_et + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->txrx.txd_size, ++ cnt * soc->tx.desc_size, + ð->phy_scratch_ring, + GFP_KERNEL); + if (unlikely(!eth->scratch_ring)) +@@ -1255,16 +1255,16 @@ static int mtk_init_fq_dma(struct mtk_et + if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + +- phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1); ++ phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1); + + for (i = 0; i < cnt; i++) { + struct mtk_tx_dma_v2 *txd; + +- txd = eth->scratch_ring + i * soc->txrx.txd_size; ++ txd = eth->scratch_ring + i * soc->tx.desc_size; + txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; + if (i < cnt - 1) + txd->txd2 = eth->phy_scratch_ring + +- (i + 1) * soc->txrx.txd_size; ++ (i + 1) * soc->tx.desc_size; + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + txd->txd4 = 0; +@@ -1511,7 +1511,7 @@ static int mtk_tx_map(struct sk_buff *sk + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + memset(itx_buf, 0, sizeof(*itx_buf)); + + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +@@ -1552,7 +1552,7 @@ static int mtk_tx_map(struct sk_buff *sk + + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = min_t(unsigned int, frag_size, +- soc->txrx.dma_max_len); ++ soc->tx.dma_max_len); + txd_info.qid = queue; + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && + !(frag_size - txd_info.size); +@@ -1565,7 +1565,7 @@ static int mtk_tx_map(struct sk_buff *sk + mtk_tx_set_dma_desc(dev, txd, &txd_info); + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +@@ -1608,7 +1608,7 @@ static int mtk_tx_map(struct sk_buff *sk + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1617,7 +1617,7 @@ static int mtk_tx_map(struct sk_buff *sk + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + + /* unmap dma */ + mtk_tx_unmap(eth, tx_buf, false); +@@ -1642,7 +1642,7 @@ static int mtk_cal_txd_req(struct mtk_et + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(skb_frag_size(frag), +- eth->soc->txrx.dma_max_len); ++ eth->soc->tx.dma_max_len); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; +@@ -1783,7 +1783,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri + + ring = ð->rx_ring[i]; + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + if (rxd->rxd2 & RX_DMA_DONE) { + ring->calc_idx_update = true; + return ring; +@@ -1951,7 +1951,7 @@ static int mtk_xdp_submit_frame(struct m + } + htxd = txd; + +- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + htx_buf = tx_buf; + +@@ -1971,7 +1971,7 @@ static int mtk_xdp_submit_frame(struct m + goto unmap; + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + n_desc++; + } +@@ -2008,7 +2008,7 @@ static int mtk_xdp_submit_frame(struct m + } else { + int idx; + +- idx = txd_to_idx(ring, txd, soc->txrx.txd_size); ++ idx = txd_to_idx(ring, txd, soc->tx.desc_size); + mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), + MT7628_TX_CTX_IDX0); + } +@@ -2020,7 +2020,7 @@ static int mtk_xdp_submit_frame(struct m + unmap: + while (htxd != txd) { + txd_pdma = qdma_to_pdma(ring, htxd); +- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size); + mtk_tx_unmap(eth, tx_buf, false); + + htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; +@@ -2148,7 +2148,7 @@ static int mtk_poll_rx(struct napi_struc + goto rx_done; + + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + data = ring->data[idx]; + + if (!mtk_rx_get_desc(eth, &trxd, rxd)) +@@ -2283,7 +2283,7 @@ static int mtk_poll_rx(struct napi_struc + rxdcsum = &trxd.rxd4; + } + +- if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid) ++ if (*rxdcsum & eth->soc->rx.dma_l4_valid) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); +@@ -2405,7 +2405,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + break; + + tx_buf = mtk_desc_to_tx_buf(ring, desc, +- eth->soc->txrx.txd_size); ++ eth->soc->tx.desc_size); + if (!tx_buf->data) + break; + +@@ -2453,7 +2453,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + } + mtk_tx_unmap(eth, tx_buf, true); + +- desc = ring->dma + cpu * eth->soc->txrx.txd_size; ++ desc = ring->dma + cpu * eth->soc->tx.desc_size; + ring->last_free = desc; + atomic_inc(&ring->free_count); + +@@ -2542,7 +2542,7 @@ static int mtk_napi_rx(struct napi_struc + do { + int rx_done; + +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, + reg_map->pdma.irq_status); + rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); + rx_done_total += rx_done; +@@ -2558,10 +2558,10 @@ static int mtk_napi_rx(struct napi_struc + return budget; + + } while (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask); ++ eth->soc->rx.irq_done_mask); + + if (napi_complete_done(napi, rx_done_total)) +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + + return rx_done_total; + } +@@ -2570,7 +2570,7 @@ static int mtk_tx_alloc(struct mtk_eth * + { + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; +- int i, sz = soc->txrx.txd_size; ++ int i, sz = soc->tx.desc_size; + struct mtk_tx_dma_v2 *txd; + int ring_size; + u32 ofs, val; +@@ -2693,14 +2693,14 @@ static void mtk_tx_clean(struct mtk_eth + } + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2755,15 +2755,15 @@ static int mtk_rx_alloc(struct mtk_eth * + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->txrx.rxd_size, +- &ring->phys, GFP_KERNEL); ++ rx_dma_size * eth->soc->rx.desc_size, ++ &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + + ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + } + + if (!ring->dma) +@@ -2774,7 +2774,7 @@ static int mtk_rx_alloc(struct mtk_eth * + dma_addr_t dma_addr; + void *data; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (ring->page_pool) { + data = mtk_page_pool_get_buff(ring->page_pool, + &dma_addr, GFP_KERNEL); +@@ -2863,7 +2863,7 @@ static void mtk_rx_clean(struct mtk_eth + if (!ring->data[i]) + continue; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (!rxd->rxd1) + continue; + +@@ -2880,7 +2880,7 @@ static void mtk_rx_clean(struct mtk_eth + + if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->txrx.rxd_size, ++ ring->dma_size * eth->soc->rx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } +@@ -3243,7 +3243,7 @@ static void mtk_dma_free(struct mtk_eth + netdev_reset_queue(eth->netdev[i]); + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->txrx.txd_size, ++ MTK_QDMA_RING_SIZE * soc->tx.desc_size, + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +@@ -3293,7 +3293,7 @@ static irqreturn_t mtk_handle_irq_rx(int + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + __napi_schedule(ð->rx_napi); + } + +@@ -3319,9 +3319,9 @@ static irqreturn_t mtk_handle_irq(int ir + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + + if (mtk_r32(eth, reg_map->pdma.irq_mask) & +- eth->soc->txrx.rx_irq_done_mask) { ++ eth->soc->rx.irq_done_mask) { + if (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask) ++ eth->soc->rx.irq_done_mask) + mtk_handle_irq_rx(irq, _eth); + } + if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { +@@ -3339,10 +3339,10 @@ static void mtk_poll_controller(struct n + struct mtk_eth *eth = mac->hw; + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + mtk_handle_irq_rx(eth->irq[2], dev); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + } + #endif + +@@ -3507,7 +3507,7 @@ static int mtk_open(struct net_device *d + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, soc->rx.irq_done_mask); + refcount_set(ð->dma_refcnt, 1); + } + else +@@ -3590,7 +3590,7 @@ static int mtk_stop(struct net_device *d + mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + +@@ -4066,9 +4066,9 @@ static int mtk_hw_init(struct mtk_eth *e + + /* FE int grouping */ + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->pdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4); + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4); + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + + if (mtk_is_netsys_v3_or_greater(eth)) { +@@ -5165,11 +5165,15 @@ static const struct mtk_soc_data mt2701_ + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5185,11 +5189,15 @@ static const struct mtk_soc_data mt7621_ + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5207,11 +5215,15 @@ static const struct mtk_soc_data mt7622_ + .hash_offset = 2, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5228,11 +5240,15 @@ static const struct mtk_soc_data mt7623_ + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5247,11 +5263,15 @@ static const struct mtk_soc_data mt7629_ + .required_pctl = false, + .has_accounting = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5269,11 +5289,15 @@ static const struct mtk_soc_data mt7981_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5291,11 +5315,15 @@ static const struct mtk_soc_data mt7986_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5313,11 +5341,15 @@ static const struct mtk_soc_data mt7988_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5330,11 +5362,15 @@ static const struct mtk_soc_data rt5350_ + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -326,8 +326,8 @@ + /* QDMA descriptor txd3 */ + #define TX_DMA_OWNER_CPU BIT(31) + #define TX_DMA_LS0 BIT(30) +-#define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) ++#define TX_DMA_PLEN0(x) (((x) & eth->soc->tx.dma_max_len) << eth->soc->tx.dma_len_offset) ++#define TX_DMA_PLEN1(x) ((x) & eth->soc->tx.dma_max_len) + #define TX_DMA_SWC BIT(14) + #define TX_DMA_PQID GENMASK(3, 0) + #define TX_DMA_ADDR64_MASK GENMASK(3, 0) +@@ -347,8 +347,8 @@ + /* QDMA descriptor rxd2 */ + #define RX_DMA_DONE BIT(31) + #define RX_DMA_LSO BIT(30) +-#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) ++#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->rx.dma_max_len) << eth->soc->rx.dma_len_offset) ++#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->rx.dma_len_offset) & eth->soc->rx.dma_max_len) + #define RX_DMA_VTAG BIT(15) + #define RX_DMA_ADDR64_MASK GENMASK(3, 0) + #if IS_ENABLED(CONFIG_64BIT) +@@ -1279,10 +1279,9 @@ struct mtk_reg_map { + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +- * @txd_size Tx DMA descriptor size. +- * @rxd_size Rx DMA descriptor size. +- * @rx_irq_done_mask Rx irq done register mask. +- * @rx_dma_l4_valid Rx DMA valid register mask. ++ * @desc_size Tx/Rx DMA descriptor size. ++ * @irq_done_mask Rx irq done register mask. ++ * @dma_l4_valid Rx DMA valid register mask. + * @dma_max_len Max DMA tx/rx buffer length. + * @dma_len_offset Tx/Rx DMA length field offset. + */ +@@ -1300,13 +1299,17 @@ struct mtk_soc_data { + bool has_accounting; + bool disable_pll_modes; + struct { +- u32 txd_size; +- u32 rxd_size; +- u32 rx_irq_done_mask; +- u32 rx_dma_l4_valid; ++ u32 desc_size; + u32 dma_max_len; + u32 dma_len_offset; +- } txrx; ++ } tx; ++ struct { ++ u32 desc_size; ++ u32 irq_done_mask; ++ u32 dma_l4_valid; ++ u32 dma_max_len; ++ u32 dma_len_offset; ++ } rx; + }; + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) diff --git a/target/linux/mediatek/patches-5.15/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch b/target/linux/mediatek/patches-5.15/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch new file mode 100644 index 0000000000..dd191f7afd --- /dev/null +++ b/target/linux/mediatek/patches-5.15/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch @@ -0,0 +1,123 @@ +From: Daniel Golle +Date: Tue, 10 Oct 2023 21:06:43 +0200 +Subject: [PATCH net-next 2/2] net: ethernet: mediatek: use QDMA instead of + ADMAv2 on MT7981 and MT7986 + +ADMA is plagued by RX hangs which can't easily detected and happen upon +receival of a corrupted package. +Use QDMA just like on netsys v1 which is also still present and usable, and +doesn't suffer from that problem. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 46 ++++++++++----------- + 1 file changed, 23 insertions(+), 23 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -108,16 +108,16 @@ static const struct mtk_reg_map mt7986_r + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { +- .rx_ptr = 0x6100, +- .rx_cnt_cfg = 0x6104, +- .pcrx_ptr = 0x6108, +- .glo_cfg = 0x6204, +- .rst_idx = 0x6208, +- .delay_irq = 0x620c, +- .irq_status = 0x6220, +- .irq_mask = 0x6228, +- .adma_rx_dbg0 = 0x6238, +- .int_grp = 0x6250, ++ .rx_ptr = 0x4100, ++ .rx_cnt_cfg = 0x4104, ++ .pcrx_ptr = 0x4108, ++ .glo_cfg = 0x4204, ++ .rst_idx = 0x4208, ++ .delay_irq = 0x420c, ++ .irq_status = 0x4220, ++ .irq_mask = 0x4228, ++ .adma_rx_dbg0 = 0x4238, ++ .int_grp = 0x4250, + }, + .qdma = { + .qtx_cfg = 0x4400, +@@ -1207,7 +1207,7 @@ static bool mtk_rx_get_desc(struct mtk_e + rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); + rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -2155,7 +2155,7 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); + + switch (val) { +@@ -2267,7 +2267,7 @@ static int mtk_poll_rx(struct napi_struc + skb->dev = netdev; + bytes += skb->len; + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -2809,7 +2809,7 @@ static int mtk_rx_alloc(struct mtk_eth * + + rxd->rxd3 = 0; + rxd->rxd4 = 0; +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -4012,7 +4012,7 @@ static int mtk_hw_init(struct mtk_eth *e + else + mtk_hw_reset(eth); + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -5295,11 +5295,11 @@ static const struct mtk_soc_data mt7981_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + +@@ -5321,11 +5321,11 @@ static const struct mtk_soc_data mt7986_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + diff --git a/target/linux/mediatek/patches-5.15/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch b/target/linux/mediatek/patches-5.15/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch new file mode 100644 index 0000000000..11b52d07ab --- /dev/null +++ b/target/linux/mediatek/patches-5.15/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch @@ -0,0 +1,49 @@ +From: Felix Fietkau +Date: Thu, 18 Jan 2024 12:51:32 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix WED + wifi reset + +The WLAN + WED reset sequence relies on being able to receive interrupts from +the card, in order to synchronize individual steps with the firmware. +When WED is stopped, leave interrupts running and rely on the driver turning +off unwanted ones. +WED DMA also needs to be disabled before resetting. + +Fixes: f78cd9c783e0 ("net: ethernet: mtk_wed: update mtk_wed_stop") +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1071,13 +1071,13 @@ mtk_wed_dma_disable(struct mtk_wed_devic + static void + mtk_wed_stop(struct mtk_wed_device *dev) + { ++ mtk_wed_dma_disable(dev); + mtk_wed_set_ext_int(dev, false); + + wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); + wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); + wdma_w32(dev, MTK_WDMA_INT_MASK, 0); + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); +- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + + if (!mtk_wed_get_rx_capa(dev)) + return; +@@ -1090,7 +1090,6 @@ static void + mtk_wed_deinit(struct mtk_wed_device *dev) + { + mtk_wed_stop(dev); +- mtk_wed_dma_disable(dev); + + wed_clr(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WDMA_INT_AGENT_EN | +@@ -2621,9 +2620,6 @@ mtk_wed_irq_get(struct mtk_wed_device *d + static void + mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) + { +- if (!dev->running) +- return; +- + mtk_wed_set_ext_int(dev, !!mask); + wed_w32(dev, MTK_WED_INT_MASK, mask); + } diff --git a/target/linux/mediatek/patches-6.1/106-dts-mt7622-disable_btif.patch b/target/linux/mediatek/patches-6.1/106-dts-mt7622-disable_btif.patch new file mode 100644 index 0000000000..fc6a8f35bc --- /dev/null +++ b/target/linux/mediatek/patches-6.1/106-dts-mt7622-disable_btif.patch @@ -0,0 +1,26 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -108,10 +108,6 @@ + status = "disabled"; + }; + +-&btif { +- status = "okay"; +-}; +- + &cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -89,10 +89,6 @@ + status = "disabled"; + }; + +-&btif { +- status = "okay"; +-}; +- + &cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; diff --git a/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch b/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch index 816683e626..b012a48d75 100644 --- a/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch +++ b/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch @@ -8,7 +8,7 @@ }; chosen { -@@ -164,22 +165,22 @@ +@@ -160,22 +161,22 @@ port@1 { reg = <1>; diff --git a/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch b/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch index 3d1b90217f..e30d9e5e12 100644 --- a/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch +++ b/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -558,12 +558,16 @@ +@@ -554,12 +554,16 @@ status = "okay"; }; diff --git a/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch b/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch index b159a17c4a..93f87fe697 100644 --- a/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch +++ b/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -255,14 +255,42 @@ +@@ -251,14 +251,42 @@ status = "disabled"; }; diff --git a/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch index 9cfe69ebb6..d6e0ab1d41 100644 --- a/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch +++ b/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -538,6 +538,65 @@ +@@ -534,6 +534,65 @@ status = "disabled"; }; diff --git a/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch index b01ce97cf0..117d5abde6 100644 --- a/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch +++ b/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -579,7 +579,7 @@ +@@ -575,7 +575,7 @@ reg = <0x140000 0x0080000>; }; @@ -9,7 +9,7 @@ label = "Factory"; reg = <0x1c0000 0x0100000>; }; -@@ -640,5 +640,6 @@ +@@ -636,5 +636,6 @@ &wmac { pinctrl-names = "default"; pinctrl-0 = <&wmac_pins>; diff --git a/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch b/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch index 5a834ac34f..676c09f656 100644 --- a/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch +++ b/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -156,6 +156,10 @@ +@@ -152,6 +152,10 @@ switch@0 { compatible = "mediatek,mt7531"; reg = <0>; diff --git a/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch b/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch index 662515f2c5..3e956701cd 100644 --- a/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch +++ b/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -552,6 +552,7 @@ +@@ -548,6 +548,7 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; nand-ecc-engine = <&snfi>; diff --git a/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch index 4f9ad9acef..9aeeb78658 100644 --- a/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ b/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -1374,6 +1374,70 @@ static int spi_transfer_wait(struct spi_ +@@ -1385,6 +1385,70 @@ static int spi_transfer_wait(struct spi_ return 0; } @@ -82,7 +82,7 @@ Signed-off-by: SkyLake.Huang static void _spi_transfer_delay_ns(u32 ns) { if (!ns) -@@ -2208,6 +2272,75 @@ void spi_flush_queue(struct spi_controll +@@ -2219,6 +2283,75 @@ void spi_flush_queue(struct spi_controll /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OF) @@ -158,7 +158,7 @@ Signed-off-by: SkyLake.Huang static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, struct device_node *nc) { -@@ -2326,6 +2459,10 @@ of_register_spi_device(struct spi_contro +@@ -2337,6 +2470,10 @@ of_register_spi_device(struct spi_contro if (rc) goto err_out; @@ -171,7 +171,7 @@ Signed-off-by: SkyLake.Huang spi->dev.of_node = nc; --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h -@@ -298,6 +298,40 @@ struct spi_driver { +@@ -318,6 +318,40 @@ struct spi_driver { struct device_driver driver; }; @@ -212,7 +212,7 @@ Signed-off-by: SkyLake.Huang static inline struct spi_driver *to_spi_driver(struct device_driver *drv) { return drv ? container_of(drv, struct spi_driver, driver) : NULL; -@@ -683,6 +717,11 @@ struct spi_controller { +@@ -703,6 +737,11 @@ struct spi_controller { void *dummy_rx; void *dummy_tx; @@ -224,7 +224,7 @@ Signed-off-by: SkyLake.Huang int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs); /* -@@ -1490,6 +1529,9 @@ spi_register_board_info(struct spi_board +@@ -1510,6 +1549,9 @@ spi_register_board_info(struct spi_board { return 0; } #endif diff --git a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch index 389b2e4c99..f4e972f658 100644 --- a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -24,7 +24,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12934,6 +12934,15 @@ S: Maintained +@@ -12936,6 +12936,15 @@ S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c F: include/linux/pcs/pcs-mtk-lynxi.h diff --git a/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch b/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch index 600b94d7bb..8e56be9ff4 100644 --- a/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch +++ b/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -314,7 +314,7 @@ +@@ -310,7 +310,7 @@ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and * SATA functions. i.e. output-high: PCIe, output-low: SATA */ diff --git a/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch b/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch index a45d51dd9f..b6762e29ac 100644 --- a/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch +++ b/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -641,5 +641,28 @@ +@@ -637,5 +637,28 @@ }; &wmac { diff --git a/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch b/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch new file mode 100644 index 0000000000..df37a61c23 --- /dev/null +++ b/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch @@ -0,0 +1,599 @@ +From: Lorenzo Bianconi +Date: Thu, 2 Nov 2023 16:47:07 +0100 +Subject: [PATCH net-next 1/2] net: ethernet: mediatek: split tx and rx fields + in mtk_soc_data struct + +Split tx and rx fields in mtk_soc_data struct. This is a preliminary +patch to roll back to QDMA for MT7986 SoC in order to fix a hw hang +if the device receives a corrupted packet. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 210 ++++++++++++-------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 29 +-- + 2 files changed, 139 insertions(+), 100 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1239,7 +1239,7 @@ static int mtk_init_fq_dma(struct mtk_et + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->txrx.txd_size, ++ cnt * soc->tx.desc_size, + ð->phy_scratch_ring, + GFP_KERNEL); + if (unlikely(!eth->scratch_ring)) +@@ -1255,16 +1255,16 @@ static int mtk_init_fq_dma(struct mtk_et + if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + +- phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1); ++ phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1); + + for (i = 0; i < cnt; i++) { + struct mtk_tx_dma_v2 *txd; + +- txd = eth->scratch_ring + i * soc->txrx.txd_size; ++ txd = eth->scratch_ring + i * soc->tx.desc_size; + txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; + if (i < cnt - 1) + txd->txd2 = eth->phy_scratch_ring + +- (i + 1) * soc->txrx.txd_size; ++ (i + 1) * soc->tx.desc_size; + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + txd->txd4 = 0; +@@ -1513,7 +1513,7 @@ static int mtk_tx_map(struct sk_buff *sk + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + memset(itx_buf, 0, sizeof(*itx_buf)); + + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +@@ -1554,7 +1554,7 @@ static int mtk_tx_map(struct sk_buff *sk + + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = min_t(unsigned int, frag_size, +- soc->txrx.dma_max_len); ++ soc->tx.dma_max_len); + txd_info.qid = queue; + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && + !(frag_size - txd_info.size); +@@ -1567,7 +1567,7 @@ static int mtk_tx_map(struct sk_buff *sk + mtk_tx_set_dma_desc(dev, txd, &txd_info); + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +@@ -1610,7 +1610,7 @@ static int mtk_tx_map(struct sk_buff *sk + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1619,7 +1619,7 @@ static int mtk_tx_map(struct sk_buff *sk + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + + /* unmap dma */ + mtk_tx_unmap(eth, tx_buf, NULL, false); +@@ -1644,7 +1644,7 @@ static int mtk_cal_txd_req(struct mtk_et + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(skb_frag_size(frag), +- eth->soc->txrx.dma_max_len); ++ eth->soc->tx.dma_max_len); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; +@@ -1785,7 +1785,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri + + ring = ð->rx_ring[i]; + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + if (rxd->rxd2 & RX_DMA_DONE) { + ring->calc_idx_update = true; + return ring; +@@ -1953,7 +1953,7 @@ static int mtk_xdp_submit_frame(struct m + } + htxd = txd; + +- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + htx_buf = tx_buf; + +@@ -1972,7 +1972,7 @@ static int mtk_xdp_submit_frame(struct m + goto unmap; + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + n_desc++; + } +@@ -2010,7 +2010,7 @@ static int mtk_xdp_submit_frame(struct m + } else { + int idx; + +- idx = txd_to_idx(ring, txd, soc->txrx.txd_size); ++ idx = txd_to_idx(ring, txd, soc->tx.desc_size); + mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), + MT7628_TX_CTX_IDX0); + } +@@ -2021,7 +2021,7 @@ static int mtk_xdp_submit_frame(struct m + + unmap: + while (htxd != txd) { +- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size); + mtk_tx_unmap(eth, tx_buf, NULL, false); + + htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; +@@ -2152,7 +2152,7 @@ static int mtk_poll_rx(struct napi_struc + goto rx_done; + + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + data = ring->data[idx]; + + if (!mtk_rx_get_desc(eth, &trxd, rxd)) +@@ -2287,7 +2287,7 @@ static int mtk_poll_rx(struct napi_struc + rxdcsum = &trxd.rxd4; + } + +- if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid) ++ if (*rxdcsum & eth->soc->rx.dma_l4_valid) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); +@@ -2411,7 +2411,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + break; + + tx_buf = mtk_desc_to_tx_buf(ring, desc, +- eth->soc->txrx.txd_size); ++ eth->soc->tx.desc_size); + if (!tx_buf->data) + break; + +@@ -2462,7 +2462,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + } + mtk_tx_unmap(eth, tx_buf, &bq, true); + +- desc = ring->dma + cpu * eth->soc->txrx.txd_size; ++ desc = ring->dma + cpu * eth->soc->tx.desc_size; + ring->last_free = desc; + atomic_inc(&ring->free_count); + +@@ -2552,7 +2552,7 @@ static int mtk_napi_rx(struct napi_struc + do { + int rx_done; + +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, + reg_map->pdma.irq_status); + rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); + rx_done_total += rx_done; +@@ -2568,10 +2568,10 @@ static int mtk_napi_rx(struct napi_struc + return budget; + + } while (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask); ++ eth->soc->rx.irq_done_mask); + + if (napi_complete_done(napi, rx_done_total)) +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + + return rx_done_total; + } +@@ -2580,7 +2580,7 @@ static int mtk_tx_alloc(struct mtk_eth * + { + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; +- int i, sz = soc->txrx.txd_size; ++ int i, sz = soc->tx.desc_size; + struct mtk_tx_dma_v2 *txd; + int ring_size; + u32 ofs, val; +@@ -2703,14 +2703,14 @@ static void mtk_tx_clean(struct mtk_eth + } + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2765,15 +2765,15 @@ static int mtk_rx_alloc(struct mtk_eth * + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->txrx.rxd_size, +- &ring->phys, GFP_KERNEL); ++ rx_dma_size * eth->soc->rx.desc_size, ++ &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + + ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + } + + if (!ring->dma) +@@ -2784,7 +2784,7 @@ static int mtk_rx_alloc(struct mtk_eth * + dma_addr_t dma_addr; + void *data; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (ring->page_pool) { + data = mtk_page_pool_get_buff(ring->page_pool, + &dma_addr, GFP_KERNEL); +@@ -2875,7 +2875,7 @@ static void mtk_rx_clean(struct mtk_eth + if (!ring->data[i]) + continue; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (!rxd->rxd1) + continue; + +@@ -2892,7 +2892,7 @@ static void mtk_rx_clean(struct mtk_eth + + if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->txrx.rxd_size, ++ ring->dma_size * eth->soc->rx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } +@@ -3255,7 +3255,7 @@ static void mtk_dma_free(struct mtk_eth + netdev_reset_queue(eth->netdev[i]); + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->txrx.txd_size, ++ MTK_QDMA_RING_SIZE * soc->tx.desc_size, + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +@@ -3305,7 +3305,7 @@ static irqreturn_t mtk_handle_irq_rx(int + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + __napi_schedule(ð->rx_napi); + } + +@@ -3331,9 +3331,9 @@ static irqreturn_t mtk_handle_irq(int ir + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + + if (mtk_r32(eth, reg_map->pdma.irq_mask) & +- eth->soc->txrx.rx_irq_done_mask) { ++ eth->soc->rx.irq_done_mask) { + if (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask) ++ eth->soc->rx.irq_done_mask) + mtk_handle_irq_rx(irq, _eth); + } + if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { +@@ -3351,10 +3351,10 @@ static void mtk_poll_controller(struct n + struct mtk_eth *eth = mac->hw; + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + mtk_handle_irq_rx(eth->irq[2], dev); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + } + #endif + +@@ -3517,7 +3517,7 @@ static int mtk_open(struct net_device *d + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, soc->rx.irq_done_mask); + refcount_set(ð->dma_refcnt, 1); + } + else +@@ -3600,7 +3600,7 @@ static int mtk_stop(struct net_device *d + mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + +@@ -4076,9 +4076,9 @@ static int mtk_hw_init(struct mtk_eth *e + + /* FE int grouping */ + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->pdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4); + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4); + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + + if (mtk_is_netsys_v3_or_greater(eth)) { +@@ -5173,11 +5173,15 @@ static const struct mtk_soc_data mt2701_ + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5193,11 +5197,15 @@ static const struct mtk_soc_data mt7621_ + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5215,11 +5223,15 @@ static const struct mtk_soc_data mt7622_ + .hash_offset = 2, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5236,11 +5248,15 @@ static const struct mtk_soc_data mt7623_ + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5255,11 +5271,15 @@ static const struct mtk_soc_data mt7629_ + .required_pctl = false, + .has_accounting = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5277,11 +5297,15 @@ static const struct mtk_soc_data mt7981_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5299,11 +5323,15 @@ static const struct mtk_soc_data mt7986_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5321,11 +5349,15 @@ static const struct mtk_soc_data mt7988_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5338,11 +5370,15 @@ static const struct mtk_soc_data rt5350_ + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -326,8 +326,8 @@ + /* QDMA descriptor txd3 */ + #define TX_DMA_OWNER_CPU BIT(31) + #define TX_DMA_LS0 BIT(30) +-#define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) ++#define TX_DMA_PLEN0(x) (((x) & eth->soc->tx.dma_max_len) << eth->soc->tx.dma_len_offset) ++#define TX_DMA_PLEN1(x) ((x) & eth->soc->tx.dma_max_len) + #define TX_DMA_SWC BIT(14) + #define TX_DMA_PQID GENMASK(3, 0) + #define TX_DMA_ADDR64_MASK GENMASK(3, 0) +@@ -347,8 +347,8 @@ + /* QDMA descriptor rxd2 */ + #define RX_DMA_DONE BIT(31) + #define RX_DMA_LSO BIT(30) +-#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) ++#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->rx.dma_max_len) << eth->soc->rx.dma_len_offset) ++#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->rx.dma_len_offset) & eth->soc->rx.dma_max_len) + #define RX_DMA_VTAG BIT(15) + #define RX_DMA_ADDR64_MASK GENMASK(3, 0) + #if IS_ENABLED(CONFIG_64BIT) +@@ -1279,10 +1279,9 @@ struct mtk_reg_map { + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +- * @txd_size Tx DMA descriptor size. +- * @rxd_size Rx DMA descriptor size. +- * @rx_irq_done_mask Rx irq done register mask. +- * @rx_dma_l4_valid Rx DMA valid register mask. ++ * @desc_size Tx/Rx DMA descriptor size. ++ * @irq_done_mask Rx irq done register mask. ++ * @dma_l4_valid Rx DMA valid register mask. + * @dma_max_len Max DMA tx/rx buffer length. + * @dma_len_offset Tx/Rx DMA length field offset. + */ +@@ -1300,13 +1299,17 @@ struct mtk_soc_data { + bool has_accounting; + bool disable_pll_modes; + struct { +- u32 txd_size; +- u32 rxd_size; +- u32 rx_irq_done_mask; +- u32 rx_dma_l4_valid; ++ u32 desc_size; + u32 dma_max_len; + u32 dma_len_offset; +- } txrx; ++ } tx; ++ struct { ++ u32 desc_size; ++ u32 irq_done_mask; ++ u32 dma_l4_valid; ++ u32 dma_max_len; ++ u32 dma_len_offset; ++ } rx; + }; + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) diff --git a/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch b/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch new file mode 100644 index 0000000000..66c28eaaaa --- /dev/null +++ b/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch @@ -0,0 +1,123 @@ +From: Daniel Golle +Date: Tue, 10 Oct 2023 21:06:43 +0200 +Subject: [PATCH net-next 2/2] net: ethernet: mediatek: use QDMA instead of + ADMAv2 on MT7981 and MT7986 + +ADMA is plagued by RX hangs which can't easily detected and happen upon +receival of a corrupted package. +Use QDMA just like on netsys v1 which is also still present and usable, and +doesn't suffer from that problem. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 46 ++++++++++----------- + 1 file changed, 23 insertions(+), 23 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -108,16 +108,16 @@ static const struct mtk_reg_map mt7986_r + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { +- .rx_ptr = 0x6100, +- .rx_cnt_cfg = 0x6104, +- .pcrx_ptr = 0x6108, +- .glo_cfg = 0x6204, +- .rst_idx = 0x6208, +- .delay_irq = 0x620c, +- .irq_status = 0x6220, +- .irq_mask = 0x6228, +- .adma_rx_dbg0 = 0x6238, +- .int_grp = 0x6250, ++ .rx_ptr = 0x4100, ++ .rx_cnt_cfg = 0x4104, ++ .pcrx_ptr = 0x4108, ++ .glo_cfg = 0x4204, ++ .rst_idx = 0x4208, ++ .delay_irq = 0x420c, ++ .irq_status = 0x4220, ++ .irq_mask = 0x4228, ++ .adma_rx_dbg0 = 0x4238, ++ .int_grp = 0x4250, + }, + .qdma = { + .qtx_cfg = 0x4400, +@@ -1207,7 +1207,7 @@ static bool mtk_rx_get_desc(struct mtk_e + rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); + rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -2159,7 +2159,7 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); + + switch (val) { +@@ -2271,7 +2271,7 @@ static int mtk_poll_rx(struct napi_struc + skb->dev = netdev; + bytes += skb->len; + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -2821,7 +2821,7 @@ static int mtk_rx_alloc(struct mtk_eth * + + rxd->rxd3 = 0; + rxd->rxd4 = 0; +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -4022,7 +4022,7 @@ static int mtk_hw_init(struct mtk_eth *e + else + mtk_hw_reset(eth); + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -5303,11 +5303,11 @@ static const struct mtk_soc_data mt7981_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + +@@ -5329,11 +5329,11 @@ static const struct mtk_soc_data mt7986_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + diff --git a/target/linux/mediatek/patches-6.1/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch b/target/linux/mediatek/patches-6.1/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch new file mode 100644 index 0000000000..11b52d07ab --- /dev/null +++ b/target/linux/mediatek/patches-6.1/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch @@ -0,0 +1,49 @@ +From: Felix Fietkau +Date: Thu, 18 Jan 2024 12:51:32 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix WED + wifi reset + +The WLAN + WED reset sequence relies on being able to receive interrupts from +the card, in order to synchronize individual steps with the firmware. +When WED is stopped, leave interrupts running and rely on the driver turning +off unwanted ones. +WED DMA also needs to be disabled before resetting. + +Fixes: f78cd9c783e0 ("net: ethernet: mtk_wed: update mtk_wed_stop") +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1071,13 +1071,13 @@ mtk_wed_dma_disable(struct mtk_wed_devic + static void + mtk_wed_stop(struct mtk_wed_device *dev) + { ++ mtk_wed_dma_disable(dev); + mtk_wed_set_ext_int(dev, false); + + wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); + wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); + wdma_w32(dev, MTK_WDMA_INT_MASK, 0); + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); +- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + + if (!mtk_wed_get_rx_capa(dev)) + return; +@@ -1090,7 +1090,6 @@ static void + mtk_wed_deinit(struct mtk_wed_device *dev) + { + mtk_wed_stop(dev); +- mtk_wed_dma_disable(dev); + + wed_clr(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WDMA_INT_AGENT_EN | +@@ -2621,9 +2620,6 @@ mtk_wed_irq_get(struct mtk_wed_device *d + static void + mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) + { +- if (!dev->running) +- return; +- + mtk_wed_set_ext_int(dev, !!mask); + wed_w32(dev, MTK_WED_INT_MASK, mask); + } diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts index 622b8662fa..0ca2edcb2c 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts @@ -123,7 +123,7 @@ pinctrl-0 = <&spi_0_pins>; pinctrl-names = "default"; cs-select = <0>; - status = "ok"; + status = "okay"; m25p80@0 { #address-cells = <1>; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts index a7d398ee0f..572812ec39 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts @@ -260,7 +260,99 @@ spi-max-frequency = <50000000>; partitions { - compatible = "qcom,smem-part"; + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x50000>; + read-only; + }; + + partition@50000 { + label = "0:mibib"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "0:qsee"; + reg = <0x60000 0x180000>; + read-only; + }; + + partition@1e0000 { + label = "0:devcfg"; + reg = <0x1e0000 0x10000>; + read-only; + }; + + partition@1f0000 { + label = "0:apdp"; + reg = <0x1f0000 0x10000>; + read-only; + }; + + partition@200000 { + label = "0:rpm"; + reg = <0x200000 0x40000>; + read-only; + }; + + partition@240000 { + label = "0:cdt"; + reg = <0x240000 0x10000>; + read-only; + }; + + partition@250000 { + label = "0:appsblenv"; + reg = <0x250000 0x20000>; + }; + + partition@270000 { + label = "0:appsbl"; + reg = <0x250000 0x100000>; + read-only; + }; + + partition@370000 { + label = "0:art"; + reg = <0x370000 0x40000>; + read-only; + }; + + partition@3b0000 { + label = "0:ethphyfw1"; + reg = <0x3b0000 0x80000>; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + aqr0_fw: firmware@0 { + reg = <0x0 0x5fc02>; + }; + }; + + partition@430000 { + label = "0:ethphyfw2"; + reg = <0x430000 0x80000>; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + aqr1_fw: firmware@0 { + reg = <0x0 0x5fc02>; + }; + }; + + partition@4b0000 { + label = "reserved"; + reg = <0x4b0000 0x350000>; + }; }; }; }; @@ -275,13 +367,19 @@ aqr113c_0: ethernet-phy@0 { compatible ="ethernet-phy-ieee802.3-c45"; reg = <0>; - reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x0_ID44778_VER1630.cld"; + nvmem-cell-names = "firmware"; + nvmem-cells = <&aqr0_fw>; }; aqr113c_8: ethernet-phy@8 { compatible ="ethernet-phy-ieee802.3-c45"; reg = <8>; - reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x8_ID44776_VER1630.cld"; + nvmem-cell-names = "firmware"; + nvmem-cells = <&aqr1_fw>; }; qca8075_16: ethernet-phy@16 { diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts index 3449964159..8fdfe981f9 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts @@ -21,6 +21,10 @@ ethernet2 = &dp3; ethernet3 = &dp2; label-mac-device = &dp6_syn; + led-boot = &led_system_blue; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_blue; }; chosen { @@ -78,6 +82,13 @@ bias-pull-up; }; }; + + i2c_3_pins: i2c-3-state { + pins = "gpio46", "gpio47"; + function = "blsp2_i2c"; + drive-strength = <8>; + bias-disable; + }; }; &blsp1_uart5 { @@ -303,3 +314,41 @@ qcom,ath11k-calibration-variant = "prpl-Haze"; }; + +&blsp1_i2c3{ + pinctrl-0 = <&i2c_3_pins>; + pinctrl-names = "default"; + status = "okay"; + + led-controller@30 { + compatible = "ti,lp5562"; + reg = <0x30>; + clock-mode = /bits/ 8 <2>; + #address-cells = <1>; + #size-cells = <0>; + + led_system_red: chan@0 { + chan-name = "red"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + color = ; + reg = <0>; + }; + + led_system_green: chan@1 { + chan-name = "green"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + color = ; + reg = <1>; + }; + + led_system_blue: chan@2 { + chan-name = "blue"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + color = ; + reg = <2>; + }; + }; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts index 5fb8f3b4de..1e8e50875f 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts @@ -234,6 +234,15 @@ label = "0:ethphyfw"; reg = <0x650000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + + aqr_fw: aqr-fw@0 { + /* Skip the QCOM MBN Header of 40 bytes */ + reg = <0x28 0x5f402>; + }; + }; }; partition@6d0000 { @@ -292,6 +301,9 @@ compatible = "ethernet-phy-ieee802.3-c45"; reg = <8>; reset-gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + + nvmem-cells = <&aqr_fw>; + nvmem-cell-names = "firmware"; }; }; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200.dtsi new file mode 100644 index 0000000000..ef67742c03 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200.dtsi @@ -0,0 +1,440 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2023, Mohammad Sayful Islam */ + +#include "ipq8074.dtsi" +#include "ipq8074-ac-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + + aliases { + serial0 = &blsp1_uart5; + serial1 = &blsp1_uart3; + /* + * Aliases as required by u-boot + * to patch MAC addresses + */ + ethernet1 = &dp2; + ethernet2 = &dp3; + ethernet3 = &dp4; + ethernet4 = &dp5; + led-boot = &led_system_blue; + led-running = &led_system_blue; + led-failsafe = &led_system_red; + led-upgrade = &led_system_green; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_0"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset-button { + label = "reset"; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps-button { + label = "wps"; + gpios = <&tlmm 67 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&tlmm { + button_pins: button-state { + pins = "gpio52", "gpio67"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio_pins: mdio-state { + mdc-pins { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + iot_pins: iot-state { + recovery-pins { + pins = "gpio22"; + function = "gpio"; + input; + }; + + reset-pins { + pins = "gpio21"; + function = "gpio"; + bias-pull-up; + }; + }; +}; + +&blsp1_uart3 { + status = "okay"; + + pinctrl-0 = <&hsuart_pins &iot_pins>; + pinctrl-names = "default"; + + /* Silicon Labs EFR32MG21 IoT */ +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + /* + * Bootloader will find the NAND DT node by the compatible and + * then "fixup" it by adding the partitions from the SMEM table + * using the legacy bindings thus making it impossible for us + * to change the partition table or utilize NVMEM for calibration. + * So add a dummy partitions node that bootloader will populate + * and set it as disabled so the kernel ignores it instead of + * printing warnings due to the broken way bootloader adds the + * partitions. + */ + partitions { + status = "disabled"; + }; + + nand@0 { + reg = <0>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "0:mibib"; + reg = <0x100000 0x100000>; + read-only; + }; + + partition@200000 { + label = "0:bootconfig"; + reg = <0x200000 0x80000>; + read-only; + }; + + partition@280000 { + label = "0:bootconfig1"; + reg = <0x280000 0x80000>; + read-only; + }; + + partition@300000 { + label = "0:qsee"; + reg = <0x300000 0x300000>; + read-only; + }; + + partition@600000 { + label = "0:qsee_1"; + reg = <0x600000 0x300000>; + read-only; + }; + + partition@900000 { + label = "0:devcfg"; + reg = <0x900000 0x80000>; + read-only; + }; + + partition@980000 { + label = "0:devcfg_1"; + reg = <0x980000 0x80000>; + read-only; + }; + + partition@a00000 { + label = "0:apdp"; + reg = <0xa00000 0x80000>; + read-only; + }; + + partition@a80000 { + label = "0:apdp_1"; + reg = <0xa80000 0x80000>; + read-only; + }; + + partition@b00000 { + label = "0:rpm"; + reg = <0xb00000 0x80000>; + read-only; + }; + + partition@b80000 { + label = "0:rpm_1"; + reg = <0xb80000 0x80000>; + read-only; + }; + + partition@c00000 { + label = "0:cdt"; + reg = <0xc00000 0x80000>; + read-only; + }; + + partition@c80000 { + label = "0:cdt_1"; + reg = <0xc80000 0x80000>; + read-only; + }; + + partition@d00000 { + label = "0:appsblenv"; + reg = <0xd00000 0x80000>; + }; + + partition@d80000 { + label = "0:appsbl"; + reg = <0xd80000 0x100000>; + read-only; + }; + + partition@e80000 { + label = "0:appsbl_1"; + reg = <0xe80000 0x100000>; + read-only; + }; + + partition@f80000 { + label = "0:art"; + reg = <0xf80000 0x80000>; + read-only; + }; + + partition@1000000 { + label = "u_env"; + reg = <0x1000000 0x40000>; + }; + + partition@1040000 { + label = "s_env"; + reg = <0x1040000 0x20000>; + }; + + partition@1060000 { + label = "devinfo"; + reg = <0x1060000 0x20000>; + read-only; + }; + + partition@1080000 { + label = "kernel"; + reg = <0x1080000 0x9600000>; + }; + + partition@1680000 { + label = "rootfs"; + reg = <0x1680000 0x9000000>; + }; + + partition@a680000 { + label = "alt_kernel"; + reg = <0xa680000 0x9600000>; + }; + + partition@ac80000 { + label = "alt_rootfs"; + reg = <0xac80000 0x9000000>; + }; + partition@13c80000 { + label = "sysdiag"; + reg = <0x13c80000 0x200000>; + read-only; + }; + partition@13e80000 { + label = "0:ethphyfw"; + reg = <0x13e80000 0x80000>; + read-only; + }; + partition@13f00000 { + label = "syscfg"; + reg = <0x13f00000 0xb800000>; + read-only; + }; + partition@1f700000 { + label = "0:wififw"; + reg = <0x1f700000 0x900000>; + read-only; + }; + }; + }; +}; + +&blsp1_i2c2 { + status = "okay"; + + led-controller@62 { + compatible = "nxp,pca9633"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x62>; + nxp,hw-blink; + + led_system_red: led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led_system_green: led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led_system_blue: led@2 { + reg = <2>; + color = ; + function = LED_FUNCTION_STATUS; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; + + qca8075_1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + qca8075_2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + qca8075_3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; + + qca8075_4: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + }; +}; + +&switch { + status = "okay"; + + switch_lan_bmp = <(ESS_PORT3 | ESS_PORT4 | ESS_PORT5)>; /* lan port bitmap */ + switch_wan_bmp = ; /* wan port bitmap */ + switch_mac_mode = ; /* mac mode for uniphy instance0*/ + + qcom,port_phyinfo { + port@2 { + port_id = <2>; + phy_address = <1>; + }; + port@3 { + port_id = <3>; + phy_address = <2>; + }; + port@4 { + port_id = <4>; + phy_address = <3>; + }; + port@5 { + port_id = <5>; + phy_address = <4>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "wan"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan1"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan2"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "lan3"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts new file mode 100644 index 0000000000..7946e5c54d --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2023, Mohammad Sayful Islam */ + +/dts-v1/; + +#include "ipq8074-512m.dtsi" +#include "ipq8174-mx4200.dtsi" + +/ { + model = "Linksys MX4200v1"; + compatible = "linksys,mx4200v1", "qcom,ipq8074"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Linksys-MX4200v1"; + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v2.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v2.dts new file mode 100644 index 0000000000..44e1b72f16 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v2.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2023, Mohammad Sayful Islam */ + +/dts-v1/; + +#include "ipq8174-mx4200.dtsi" + +/ { + model = "Linksys MX4200v2"; + compatible = "linksys,mx4200v2", "qcom,ipq8074"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Linksys-MX4200v2"; +}; diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk index d8416d10fb..f5f0e26140 100644 --- a/target/linux/qualcommax/image/ipq807x.mk +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -115,6 +115,31 @@ define Device/edimax_cax1800 endef TARGET_DEVICES += edimax_cax1800 +define Device/linksys_mx4200v1 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Linksys + DEVICE_MODEL := MX4200 + DEVICE_VARIANT := v1 + BLOCKSIZE := 128k + PAGESIZE := 2048 + KERNEL_SIZE := 6144k + IMAGE_SIZE := 147456k + NAND_SIZE := 512m + KERNEL_IN_UBI := + SOC := ipq8174 + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=MX4200 + DEVICE_PACKAGES := kmod-leds-pca963x ipq-wifi-linksys_mx4200 kmod-bluetooth +endef +TARGET_DEVICES += linksys_mx4200v1 + +define Device/linksys_mx4200v2 + $(call Device/linksys_mx4200v1) + DEVICE_VARIANT := v2 +endef +TARGET_DEVICES += linksys_mx4200v2 + define Device/netgear_rax120v2 $(call Device/FitImage) $(call Device/UbiFit) @@ -195,7 +220,7 @@ define Device/prpl_haze DEVICE_DTS_CONFIG := config@hk09 SOC := ipq8072 DEVICE_PACKAGES += ath11k-firmware-qcn9074 ipq-wifi-prpl_haze kmod-ath11k-pci \ - mkf2fs f2fsck kmod-fs-f2fs + mkf2fs f2fsck kmod-fs-f2fs kmod-leds-lp5562 endef TARGET_DEVICES += prpl_haze diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network index 5da17db3fa..f38c4b6698 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network +++ b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network @@ -18,6 +18,8 @@ ipq807x_setup_interfaces() ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; compex,wpq873|\ + linksys,mx4200v1|\ + linksys,mx4200v2|\ redmi,ax6|\ xiaomi,ax3600) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" @@ -55,9 +57,33 @@ ipq807x_setup_interfaces() esac } +ipq807x_setup_macs() +{ + local board="$1" + local lan_mac="" + local wan_mac="" + local label_mac="" + + case "$board" in + linksys,mx4200v1|\ + linksys,mx4200v2) + label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) + for i in $(seq 3 5); do + [ "$(mtd_get_mac_ascii u_env eth${i}addr)" != "$label_mac" ] && lan_mac=$label_mac + done + [ "$(mtd_get_mac_ascii u_env eth2addr)" != "$label_mac" ] && wan_mac=$label_mac + ;; + esac + + [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac + [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac + [ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac +} + board_config_update board=$(board_name) ipq807x_setup_interfaces $board +ipq807x_setup_macs $board board_config_flush exit 0 diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata index ac1405739d..85d107079e 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata @@ -15,6 +15,8 @@ case "$FIRMWARE" in dynalink,dl-wrx36|\ edgecore,eap102|\ edimax,cax1800|\ + linksys,mx4200v1|\ + linksys,mx4200v2|\ netgear,rax120v2|\ netgear,wax218|\ netgear,wax620|\ diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index 3573942c54..343e42d634 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -14,6 +14,17 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 1 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress ;; + buffalo,wxr-5950ax12) + [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 8 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 16 > /sys${DEVPATH}/macaddress + ;; + linksys,mx4200v1|\ + linksys,mx4200v2) + label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) + [ "$PHYNBR" = "0" ] && macaddr_add $label_mac 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $label_mac 1 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "2" ] && macaddr_add $label_mac 3 > /sys${DEVPATH}/macaddress + ;; zte,mf269) [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 3 > /sys${DEVPATH}/macaddress diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount index 84f826b3b8..f5f6c909e9 100755 --- a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount +++ b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount @@ -10,5 +10,9 @@ boot() { # Unset changed flag after sysupgrade complete fw_setenv changed ;; + linksys,mx4200v1|\ + linksys,mx4200v2) + mtd resetbc s_env || true + ;; esac } diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity new file mode 100755 index 0000000000..05d13fff63 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common + +START=93 + +enable_affinity_ipq807x() { + set_affinity() { + irq=$(awk "/$1/{ print substr(\$1, 1, length(\$1)-1); exit }" /proc/interrupts) + [ -n "$irq" ] && echo $2 > /proc/irq/$irq/smp_affinity + } + + # assign 4 rx interrupts to each core + set_affinity 'reo2host-destination-ring1' 1 + set_affinity 'reo2host-destination-ring2' 2 + set_affinity 'reo2host-destination-ring3' 4 + set_affinity 'reo2host-destination-ring4' 8 + + # assign 3 tcl completions to last 3 CPUs + set_affinity 'wbm2host-tx-completions-ring1' 2 + set_affinity 'wbm2host-tx-completions-ring2' 4 + set_affinity 'wbm2host-tx-completions-ring3' 8 + + # assign 3 ppdu mac interrupts to last 3 cores + set_affinity 'ppdu-end-interrupts-mac1' 2 + set_affinity 'ppdu-end-interrupts-mac2' 4 + set_affinity 'ppdu-end-interrupts-mac3' 8 + + # assign lan/wan to core 4 + set_affinity 'edma_txcmpl' 8 + set_affinity 'edma_rxfill' 8 + set_affinity 'edma_rxdesc' 8 + set_affinity 'edma_misc' 8 +} + +boot() { + enable_affinity_ipq807x +} diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh index 67fd0f5402..78842e1c4d 100644 --- a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -73,6 +73,21 @@ platform_do_upgrade() { fw_setenv upgrade_available 1 nand_do_upgrade "$1" ;; + linksys,mx4200v1|\ + linksys,mx4200v2) + boot_part="$(fw_printenv -n boot_part)" + if [ "$boot_part" -eq "1" ]; then + fw_setenv boot_part 2 + CI_KERNPART="alt_kernel" + CI_UBIPART="alt_rootfs" + else + fw_setenv boot_part 1 + CI_UBIPART="rootfs" + fi + fw_setenv boot_part_ready 3 + fw_setenv auto_recovery yes + nand_do_upgrade "$1" + ;; prpl,haze|\ qnap,301w) kernelname="0:HLOS" diff --git a/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch b/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch index dd57eae360..5a4b1bbc99 100644 --- a/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch +++ b/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch @@ -15,7 +15,7 @@ Link: https://lore.kernel.org/r/20220818220628.339366-9-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -675,6 +675,14 @@ +@@ -677,6 +677,14 @@ #mbox-cells = <1>; }; diff --git a/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch b/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch index bad75e4597..f5abd27965 100644 --- a/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch +++ b/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch @@ -20,7 +20,7 @@ Link: https://lore.kernel.org/r/20220818220245.338396-5-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -274,6 +274,16 @@ +@@ -276,6 +276,16 @@ status = "disabled"; }; @@ -37,7 +37,7 @@ Link: https://lore.kernel.org/r/20220818220245.338396-5-robimarko@gmail.com cryptobam: dma-controller@704000 { compatible = "qcom,bam-v1.7.0"; reg = <0x00704000 0x20000>; -@@ -874,4 +884,90 @@ +@@ -876,4 +886,90 @@ , ; }; diff --git a/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch b/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch index e229851649..96b49e60bf 100644 --- a/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch +++ b/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch @@ -18,7 +18,7 @@ Link: https://lore.kernel.org/r/20220818220849.339732-4-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -680,6 +680,8 @@ +@@ -682,6 +682,8 @@ apcs_glb: mailbox@b111000 { compatible = "qcom,ipq8074-apcs-apps-global"; reg = <0x0b111000 0x1000>; diff --git a/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch b/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch index 1f99de002b..0f3fdfe4d4 100644 --- a/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch +++ b/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch @@ -20,7 +20,7 @@ Link: https://lore.kernel.org/r/20221030175703.1103224-3-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -361,9 +361,11 @@ +@@ -363,9 +363,11 @@ gcc: gcc@1800000 { compatible = "qcom,gcc-ipq8074"; reg = <0x01800000 0x80000>; diff --git a/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch b/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch index 1ce1140682..c9fef2cab4 100644 --- a/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch +++ b/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch @@ -17,7 +17,7 @@ Link: https://lore.kernel.org/r/20221108142357.67202-2-krzysztof.kozlowski@linar --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -318,35 +318,35 @@ +@@ -320,35 +320,35 @@ interrupt-controller; #interrupt-cells = <0x2>; diff --git a/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch b/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch index 8719bf74c4..2578aa9343 100644 --- a/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch +++ b/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch @@ -14,7 +14,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -766,6 +766,7 @@ +@@ -768,6 +768,7 @@ linux,pci-domain = <1>; bus-range = <0x00 0xff>; num-lanes = <1>; diff --git a/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch b/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch index e720eb2b85..98e0a08a27 100644 --- a/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch +++ b/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch @@ -17,7 +17,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -896,6 +896,14 @@ +@@ -898,6 +898,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 4>; @@ -32,7 +32,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; nss0-thermal { -@@ -903,6 +911,14 @@ +@@ -905,6 +913,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 5>; @@ -47,7 +47,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; nss1-thermal { -@@ -910,6 +926,14 @@ +@@ -912,6 +928,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 6>; @@ -62,7 +62,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phya0-thermal { -@@ -917,6 +941,14 @@ +@@ -919,6 +943,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 7>; @@ -77,7 +77,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phya1-thermal { -@@ -924,6 +956,14 @@ +@@ -926,6 +958,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 8>; @@ -92,7 +92,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu0_thermal: cpu0-thermal { -@@ -931,6 +971,14 @@ +@@ -933,6 +973,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 9>; @@ -107,7 +107,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu1_thermal: cpu1-thermal { -@@ -938,6 +986,14 @@ +@@ -940,6 +988,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 10>; @@ -122,7 +122,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu2_thermal: cpu2-thermal { -@@ -945,6 +1001,14 @@ +@@ -947,6 +1003,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 11>; @@ -137,7 +137,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu3_thermal: cpu3-thermal { -@@ -952,6 +1016,14 @@ +@@ -954,6 +1018,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 12>; @@ -152,7 +152,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cluster_thermal: cluster-thermal { -@@ -959,6 +1031,14 @@ +@@ -961,6 +1033,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 13>; @@ -167,7 +167,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phyb0-thermal { -@@ -966,6 +1046,14 @@ +@@ -968,6 +1048,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 14>; @@ -182,7 +182,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phyb1-thermal { -@@ -973,6 +1061,14 @@ +@@ -975,6 +1063,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 15>; diff --git a/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch b/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch index 5ae4fb5671..dee770e4cd 100644 --- a/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch +++ b/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch @@ -19,7 +19,7 @@ Reviewed-by: Konrad Dybcio --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -682,8 +682,8 @@ +@@ -684,8 +684,8 @@ apcs_glb: mailbox@b111000 { compatible = "qcom,ipq8074-apcs-apps-global"; reg = <0x0b111000 0x1000>; diff --git a/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch b/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch index 69d4126f76..4bd0d9298f 100644 --- a/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch +++ b/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch @@ -17,7 +17,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -396,8 +396,8 @@ +@@ -398,8 +398,8 @@ gcc: gcc@1800000 { compatible = "qcom,gcc-ipq8074"; reg = <0x01800000 0x80000>; diff --git a/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch b/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch index 9fefd8852a..2aedbd7028 100644 --- a/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch +++ b/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch @@ -12,7 +12,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -699,7 +699,7 @@ +@@ -701,7 +701,7 @@ reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>; ranges = <0 0xb00a000 0xffd>; @@ -21,7 +21,7 @@ Signed-off-by: Robert Marko compatible = "arm,gic-v2m-frame"; msi-controller; reg = <0x0 0xffd>; -@@ -811,8 +811,7 @@ +@@ -813,8 +813,7 @@ ranges = <0x81000000 0x0 0x00000000 0x10200000 0x0 0x10000>, /* I/O */ <0x82000000 0x0 0x10220000 0x10220000 0x0 0xfde0000>; /* MEM */ @@ -31,7 +31,7 @@ Signed-off-by: Robert Marko #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc 0 142 -@@ -873,8 +872,7 @@ +@@ -875,8 +874,7 @@ ranges = <0x81000000 0x0 0x00000000 0x20200000 0x0 0x10000>, /* I/O */ <0x82000000 0x0 0x20220000 0x20220000 0x0 0xfde0000>; /* MEM */ diff --git a/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch b/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch index e37ba37e96..f5f93d389e 100644 --- a/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch +++ b/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch @@ -49,7 +49,7 @@ Signed-off-by: Robert Marko soc: soc { #address-cells = <0x1>; #size-cells = <0x1>; -@@ -409,6 +435,11 @@ +@@ -411,6 +437,11 @@ #hwlock-cells = <1>; }; @@ -61,7 +61,7 @@ Signed-off-by: Robert Marko spmi_bus: spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0200f000 0x001000>, -@@ -913,6 +944,56 @@ +@@ -915,6 +946,56 @@ "axi_s_sticky"; status = "disabled"; }; diff --git a/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch b/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch index bd5410c934..1aaa187d8a 100644 --- a/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch +++ b/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch @@ -15,7 +15,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -994,6 +994,117 @@ +@@ -996,6 +996,117 @@ }; }; }; diff --git a/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch b/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch index 3a6f4e9c87..5776ab1af7 100644 --- a/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch +++ b/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch @@ -12,7 +12,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -340,6 +340,113 @@ +@@ -342,6 +342,113 @@ status = "disabled"; }; diff --git a/target/linux/ramips/dts/mt7620a.dtsi b/target/linux/ramips/dts/mt7620a.dtsi index a1dfa8c730..0fa503e7a2 100644 --- a/target/linux/ramips/dts/mt7620a.dtsi +++ b/target/linux/ramips/dts/mt7620a.dtsi @@ -490,8 +490,8 @@ compatible = "mediatek,mt7620-gsw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>; - reset-names = "esw"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/mt7620a_engenius_epg600.dts b/target/linux/ramips/dts/mt7620a_engenius_epg600.dts index f64676d8fb..4b3332d2f0 100644 --- a/target/linux/ramips/dts/mt7620a_engenius_epg600.dts +++ b/target/linux/ramips/dts/mt7620a_engenius_epg600.dts @@ -215,9 +215,9 @@ }; &pcie0 { - wifi@0,1,0 { + wifi@0,0 { compatible = "pci1814,3091"; - reg = <0x0 1 0 0 0>; + reg = <0x0000 0 0 0 0>; nvmem-cells = <&eeprom_factory_0>; nvmem-cell-names = "eeprom"; }; diff --git a/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi b/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi index e903f9f729..8c565385e8 100644 --- a/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi +++ b/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi @@ -38,14 +38,12 @@ compatible = "gpio-leds"; status_green: led-0 { - label = "green:status"; gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; color = ; function = LED_FUNCTION_STATUS; }; status_amber: led-1 { - label = "amber:status"; gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; color = ; function = LED_FUNCTION_STATUS; diff --git a/target/linux/ramips/dts/mt7620n.dtsi b/target/linux/ramips/dts/mt7620n.dtsi index f4a5165704..4f07c6bc4b 100644 --- a/target/linux/ramips/dts/mt7620n.dtsi +++ b/target/linux/ramips/dts/mt7620n.dtsi @@ -317,8 +317,8 @@ compatible = "mediatek,mt7620-gsw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>; - reset-names = "esw"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi b/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi index 7b3f316a8c..93570823b3 100644 --- a/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi +++ b/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi @@ -17,15 +17,13 @@ leds { compatible = "gpio-leds"; - led_status_green: led-1 { - label = "green:status"; + led_status_green: led-0 { color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; - led_status_red: led-2 { - label = "red:status"; + led_status_red: led-1 { color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_LOW>; @@ -35,7 +33,7 @@ keys { compatible = "gpio-keys"; - reset { + button-0 { label = "reset"; gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts b/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts index d18a503b85..c7d0e1e748 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts +++ b/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts @@ -104,9 +104,17 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -157,7 +165,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts b/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts index 8466cda587..94825f9de3 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts +++ b/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts @@ -96,9 +96,17 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -130,7 +138,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts index d373a801d2..36f2532161 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts @@ -7,8 +7,7 @@ model = "Beeline SmartBox Flash"; leds { - led-0 { - label = "blue:wan"; + led-2 { color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts index f2a99a63a8..c1bf5c899b 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts @@ -23,21 +23,18 @@ compatible = "gpio-leds"; led_status_green: led-0 { - label = "green:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; led-1 { - label = "blue:wan"; color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; @@ -47,7 +44,7 @@ keys { compatible = "gpio-keys"; - reset { + button-0 { label = "reset"; gpios = <&gpio 4 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts index e2c0165e6b..912b191049 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts @@ -11,7 +11,7 @@ }; keys { - switch_bt { + switch-0 { label = "ROUT<->REP Switch_bt"; gpios = <&gpio 6 GPIO_ACTIVE_LOW>; linux,input-type = ; @@ -39,7 +39,6 @@ }; &led_wps { - label = "blue:wps"; color = ; }; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts index 00f4957c57..4af425a648 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts @@ -23,21 +23,18 @@ compatible = "gpio-leds"; led-0 { - label = "blue:wan"; color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; led_status_green: led-1 { - label = "green:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; @@ -47,13 +44,13 @@ keys { compatible = "gpio-keys"; - wps { + button-0 { label = "wps"; gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; linux,code = ; }; - reset { + button-1 { label = "reset"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts b/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts index ac0c19c022..5730ca04d3 100644 --- a/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts +++ b/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts @@ -59,7 +59,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; @@ -96,6 +97,10 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_e000: macaddr@e000 { compatible = "mac-base"; reg = <0xe000 0x6>; diff --git a/target/linux/ramips/dts/mt7621_cudy_m1800.dts b/target/linux/ramips/dts/mt7621_cudy_m1800.dts index 29d6f9e41a..2c9ab5cce6 100644 --- a/target/linux/ramips/dts/mt7621_cudy_m1800.dts +++ b/target/linux/ramips/dts/mt7621_cudy_m1800.dts @@ -80,7 +80,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; @@ -116,6 +117,16 @@ label = "factory"; reg = <0x40000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; partition@50000 { diff --git a/target/linux/ramips/dts/mt7621_cudy_wr2100.dts b/target/linux/ramips/dts/mt7621_cudy_wr2100.dts index fc38e27ac1..afccce15cc 100644 --- a/target/linux/ramips/dts/mt7621_cudy_wr2100.dts +++ b/target/linux/ramips/dts/mt7621_cudy_wr2100.dts @@ -97,7 +97,7 @@ }; &pcie1 { - wifi@1,0 { + wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; nvmem-cells = <&eeprom_factory_8000>; diff --git a/target/linux/ramips/dts/mt7621_cudy_x6.dtsi b/target/linux/ramips/dts/mt7621_cudy_x6.dtsi index 4c34f58a4b..8b3baa9f84 100644 --- a/target/linux/ramips/dts/mt7621_cudy_x6.dtsi +++ b/target/linux/ramips/dts/mt7621_cudy_x6.dtsi @@ -79,6 +79,16 @@ label = "factory"; reg = <0x40000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; /* additional partitions in DTS */ @@ -94,7 +104,8 @@ wifi:wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts b/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts index c06c5e36ba..7a5fbeeddb 100644 --- a/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts @@ -98,6 +98,20 @@ label = "factory"; reg = <0x100000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@180000 { @@ -155,7 +169,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts b/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts index 73f6247b47..82b7c8070e 100644 --- a/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts @@ -134,9 +134,17 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -177,7 +185,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_etisalat_s3.dts b/target/linux/ramips/dts/mt7621_etisalat_s3.dts index 64e21bb704..2581e05a90 100644 --- a/target/linux/ramips/dts/mt7621_etisalat_s3.dts +++ b/target/linux/ramips/dts/mt7621_etisalat_s3.dts @@ -23,21 +23,18 @@ compatible = "gpio-leds"; led-0 { - label = "blue:wan"; color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; led_status_green: led-1 { - label = "green:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; @@ -47,13 +44,13 @@ keys { compatible = "gpio-keys"; - wps { + button-0 { label = "wps"; gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; linux,code = ; }; - reset { + button-1 { label = "reset"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts index 8e778ce4fe..8936258409 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts @@ -7,6 +7,11 @@ model = "I-O DATA WN-AX1167GR2"; }; +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_0 { + reg = <0x0 0x4da8>; +}; + &partitions { partition@6b00000 { label = "Backup"; @@ -19,6 +24,7 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts index eb6908629a..017d977d44 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts @@ -19,8 +19,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2483000>; }; }; @@ -29,8 +29,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 5710000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts index b9b901a6ce..c21f456a74 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts @@ -137,6 +137,10 @@ reg = <0x4 0x6>; #nvmem-cell-cells = <1>; }; + + precal: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -221,8 +225,8 @@ compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - nvmem-cells = <&eeprom>; - nvmem-cell-names = "eeprom"; + nvmem-cells = <&eeprom>, <&precal>; + nvmem-cell-names = "eeprom", "precal"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts b/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts index 4492f43f9f..c8aaa80b54 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts @@ -7,6 +7,11 @@ model = "I-O DATA WN-DX1167R"; }; +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_0 { + reg = <0x0 0x4da8>; +}; + &partitions { partition@6b00000 { label = "idmkey"; @@ -25,6 +30,7 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts index ce02def7ff..728deeba98 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts @@ -25,7 +25,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2483000>; }; }; @@ -34,7 +35,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 5710000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi index f25d2db9b3..5ed92cf0e7 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi +++ b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi @@ -86,6 +86,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; diff --git a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts index ec02679c23..a0df60234e 100644 --- a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts +++ b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts @@ -82,11 +82,19 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { compatible = "mac-base"; reg = <0x4 0x6>; #nvmem-cell-cells = <1>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -170,6 +178,7 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; }; }; diff --git a/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts b/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts index 71e8dcedbf..35a90ea070 100644 --- a/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts +++ b/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts @@ -7,6 +7,11 @@ model = "Linksys EA6350 v4"; }; +/* override EEPROM size to 0x400 for MT7603 */ +&eeprom_factory_0 { + reg = <0x0 0x400>; +}; + &gmac1 { phy-handle = <ðphy4>; }; diff --git a/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts b/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts index 4ee148828a..e3336c1dbb 100644 --- a/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts +++ b/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts @@ -6,3 +6,8 @@ compatible = "linksys,ea7300-v2", "mediatek,mt7621-soc"; model = "Linksys EA7300 v2"; }; + +/* override EEPROM size to 0x400 for MT7603 */ +&eeprom_factory_0 { + reg = <0x0 0x400>; +}; diff --git a/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi b/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi index 4663d873fe..4980b4fe9b 100644 --- a/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi +++ b/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi @@ -101,6 +101,20 @@ label = "factory"; reg = <0xc0000 0x40000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x4da8>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + }; }; partition@100000 { @@ -165,7 +179,8 @@ mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; @@ -173,7 +188,8 @@ mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts b/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts index d663dc63b2..9004e5f0fd 100644 --- a/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts +++ b/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts @@ -99,6 +99,16 @@ label = "radio"; reg = <0xff0000 0x010000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -112,9 +122,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; - nvmem-cells = <&macaddr_config_8 0>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_radio_0>, <&macaddr_config_8 0>; + nvmem-cell-names = "eeprom", "mac-address"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_eax12.dts b/target/linux/ramips/dts/mt7621_netgear_eax12.dts index d5ad404be0..d0e0eb247a 100644 --- a/target/linux/ramips/dts/mt7621_netgear_eax12.dts +++ b/target/linux/ramips/dts/mt7621_netgear_eax12.dts @@ -110,6 +110,20 @@ label = "Factory"; reg = <0x100000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@180000 { @@ -171,7 +185,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi index f5cffb4a2a..1ae7fd0f57 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi @@ -147,7 +147,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -156,7 +157,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; @@ -348,6 +350,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x4da8>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_4: macaddr@4 { compatible = "mac-base"; reg = <0x4 0x6>; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi index fd73bfcb3e..72ff75cefa 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi @@ -81,7 +81,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; @@ -90,7 +91,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -275,6 +277,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_4: macaddr@4 { compatible = "mac-base"; reg = <0x4 0x6>; diff --git a/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi b/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi index 36d576108d..0416a5f980 100644 --- a/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi +++ b/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi @@ -19,22 +19,19 @@ leds { compatible = "gpio-leds"; - led-1 { - label = "blue:wan"; + led-0 { color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; - led_status_green: led-0 { - label = "green:status"; + led_status_green: led-1 { color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; @@ -44,13 +41,13 @@ keys { compatible = "gpio-keys"; - wps { + button-0 { label = "wps"; gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; linux,code = ; }; - reset { + button-1 { label = "reset"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi b/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi index 09862b8067..d03e0da548 100644 --- a/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi +++ b/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi @@ -17,13 +17,13 @@ keys { compatible = "gpio-keys"; - reset { + button-0 { label = "reset"; gpios = <&gpio 7 GPIO_ACTIVE_LOW>; linux,code = ; }; - wps { + button-1 { label = "wps"; gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; @@ -34,33 +34,29 @@ compatible = "gpio-leds"; led-0 { - label = "amber:lan4"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <0>; + function-enumerator = <4>; linux,default-trigger = "mt7530-0:00:1Gbps"; gpios = <&gpio 3 GPIO_ACTIVE_LOW>; }; led-1 { - label = "green:lan4"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <1>; + function-enumerator = <4>; gpios = <&gpio 4 GPIO_ACTIVE_LOW>; }; led-2 { - label = "amber:lan3"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <2>; + function-enumerator = <3>; linux,default-trigger = "mt7530-0:01:1Gbps"; gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; led-3 { - label = "green:lan3"; color = ; function = LED_FUNCTION_LAN; function-enumerator = <3>; @@ -68,86 +64,73 @@ }; led-4 { - label = "amber:lan2"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <4>; + function-enumerator = <2>; linux,default-trigger = "mt7530-0:02:1Gbps"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; led-5 { - label = "amber:lan1"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <5>; + function-enumerator = <1>; linux,default-trigger = "mt7530-0:03:1Gbps"; gpios = <&gpio 22 GPIO_ACTIVE_LOW>; }; led-6 { - label = "green:lan1"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <6>; + function-enumerator = <1>; gpios = <&gpio 23 GPIO_ACTIVE_LOW>; }; led-7 { - label = "amber:wan"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <0>; linux,default-trigger = "mt7530-0:04:1Gbps"; gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; led-8 { - label = "green:wan"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <1>; gpios = <&gpio 25 GPIO_ACTIVE_LOW>; }; led-9 { - label = "green:lan2"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <7>; + function-enumerator = <2>; gpios = <&gpio 26 GPIO_ACTIVE_LOW>; }; led-10 { - label = "white:wlan2g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <0>; - linux,default-trigger = "phy1radio"; + function-enumerator = <24>; + linux,default-trigger = "phy1tpt"; gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; led_wps: led-11 { function = LED_FUNCTION_WPS; - function-enumerator = <0>; gpios = <&gpio 29 GPIO_ACTIVE_LOW>; panic-indicator; }; led_status: led-12 { - label = "white:status"; color = ; function = LED_FUNCTION_STATUS; - function-enumerator = <0>; gpios = <&gpio 30 GPIO_ACTIVE_LOW>; }; led-13 { - label = "white:wlan5g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <1>; - linux,default-trigger = "phy0radio"; + function-enumerator = <50>; + linux,default-trigger = "phy0tpt"; gpios = <&gpio 32 GPIO_ACTIVE_LOW>; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts b/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts index 1bc3f7e4f5..4de71d9e42 100644 --- a/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts @@ -132,6 +132,16 @@ label = "radio"; reg = <0xff0000 0x010000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -145,9 +155,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; - nvmem-cells = <&macaddr_config_8 0>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_radio_0>, <&macaddr_config_8 0>; + nvmem-cell-names = "eeprom", "mac-address"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts b/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts index cf08452c50..6c66401580 100644 --- a/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts @@ -113,6 +113,16 @@ label = "radio"; reg = <0xff0000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -133,7 +143,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; + nvmem-cells = <&eeprom_radio_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts b/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts index f9bbd9b392..b856488539 100644 --- a/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts @@ -133,6 +133,16 @@ label = "radio"; reg = <0xff0000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -153,7 +163,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; + nvmem-cells = <&eeprom_radio_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts b/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts index 84b3efe8df..a1b458edd5 100644 --- a/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts @@ -29,67 +29,54 @@ led-0 { color = ; function = LED_FUNCTION_USB; - function-enumerator = <0>; gpios = <&gpio 0 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>; linux,default-trigger = "usbport"; }; led-1 { - label = "blue:wps"; color = ; function = LED_FUNCTION_WPS; - function-enumerator = <0>; gpios = <&gpio 5 GPIO_ACTIVE_LOW>; }; led-2 { - label = "blue:ethernet"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <0>; gpios = <&gpio 9 GPIO_ACTIVE_LOW>; }; led-3 { - label = "amber:internet"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <0>; gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; led-4 { - label = "blue:internet"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <1>; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; led-5 { - label = "blue:wireless_5g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <0>; + function-enumerator = <50>; gpios = <&gpio 15 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1tpt"; }; led-6 { - label = "blue:wireless_2g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <1>; + function-enumerator = <24>; gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0tpt"; }; led_power: led-7 { - label = "blue:power"; color = ; - function = LED_FUNCTION_STATUS; - function-enumerator = <0>; + function = LED_FUNCTION_POWER; gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; }; @@ -97,28 +84,28 @@ keys { compatible = "gpio-keys"; - led { + button-0 { label = "led"; gpios = <&gpio 4 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; - wifi { + button-1 { label = "wifi on/off"; gpios = <&gpio 7 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; - reset { + button-2 { label = "reset"; gpios = <&gpio 8 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; - wps { + button-3 { label = "wps"; gpios = <&gpio 10 GPIO_ACTIVE_LOW>; debounce-interval = <60>; diff --git a/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts b/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts index c809cb0c0b..ffefd07d85 100644 --- a/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts @@ -161,6 +161,20 @@ label = "radio"; reg = <0x90000 0x20000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_radio_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@b0000 { @@ -186,9 +200,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; - nvmem-cells = <&macaddr_rom_file_f100 0>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_radio_0>, <&precal_radio_e10>, <&macaddr_rom_file_f100 0>; + nvmem-cell-names = "eeprom", "precal", "mac-address"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts index cd19893e14..d439e124e3 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts @@ -49,6 +49,14 @@ eeprom_factory_0: eeprom@0 { reg = <0x0 0x400>; }; + + eeprom_factory_20000: eeprom@20000 { + reg = <0x20000 0xe00>; + }; + + precal_factory_20e10: precal@20e10 { + reg = <0x20e10 0x19c10>; + }; }; }; @@ -112,8 +120,6 @@ &wlan_5g { compatible = "mediatek,mt76"; - mediatek,mtd-eeprom = <&factory 0x20000>; - /* This is a workaround. * * Ubiquiti uses a +2 offset in the first octet relative @@ -126,8 +132,8 @@ * mac80211 increases the first octet by two for each VAP, leading * to conflicting MAC addresses for subsequent interfaces. */ - nvmem-cells = <&macaddr_eeprom_6 1>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_eeprom_6 1>, <&eeprom_factory_20000>, <&precal_factory_20e10>; + nvmem-cell-names = "mac-address", "eeprom", "precal"; ieee80211-freq-limit = <5000000 6000000>; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts index 36df3ef883..d458b91ca6 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts @@ -61,6 +61,20 @@ label = "factory"; reg = <0x70000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + }; }; eeprom: partition@80000 { @@ -128,22 +142,20 @@ &pcie0 { wifi@0,0 { reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; // On newer devices there is a MediaTek MAC in the above // device EEPROM, so override it with a calculated one. - nvmem-cells = <&macaddr_eeprom_0 1>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_factory_0>, <&macaddr_eeprom_0 1>; + nvmem-cell-names = "eeprom", "mac-address"; }; }; &pcie1 { wifi@0,0 { reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; // On newer devices there is a MediaTek MAC in the above // device EEPROM, so override it with a calculated one. - nvmem-cells = <&macaddr_eeprom_0 2>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_factory_8000>, <&macaddr_eeprom_0 2>; + nvmem-cell-names = "eeprom", "mac-address"; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts index b4000464f7..d81a23852d 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts @@ -36,6 +36,20 @@ label = "factory"; reg = <0x70000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + }; }; eeprom: partition@80000 { @@ -86,9 +100,11 @@ }; &wlan_2g { - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; &wlan_5g { - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; }; diff --git a/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts b/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts index c933e443c1..d6189f3d58 100644 --- a/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts +++ b/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts @@ -13,7 +13,7 @@ flash@0 { compatible = "jedec,spi-nor"; reg = <0>; - spi-max-frequency = <14000000>; + spi-max-frequency = <50000000>; partitions { compatible = "fixed-partitions"; diff --git a/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts b/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts index 9a601d6d18..b5493a137e 100644 --- a/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts +++ b/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts @@ -7,6 +7,11 @@ model = "Wavlink WL-WN533A8"; }; +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_0 { + reg = <0x0 0x4da8>; +}; + &wifi0{ ieee80211-freq-limit = <2400000 5490000>; }; diff --git a/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi b/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi index e0db05724e..7df61c4eb3 100644 --- a/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi +++ b/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi @@ -101,6 +101,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; @@ -134,7 +142,8 @@ wifi0: mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; @@ -142,7 +151,8 @@ wifi1: mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; }; }; diff --git a/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts b/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts index dd2150c1a6..ec94e30a8c 100644 --- a/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts +++ b/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts @@ -61,7 +61,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; }; }; @@ -95,6 +96,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + macaddr_factory_3fff4: macaddr@3fff4 { reg = <0x3fff4 0x6>; }; diff --git a/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts b/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts index 4ffe988153..a3cc6038c0 100644 --- a/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts +++ b/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts @@ -28,7 +28,6 @@ }; &led_wps { - label = "white:wps"; color = ; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts index 763973a193..bd8400c898 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts @@ -86,7 +86,8 @@ wifi@0,0 { compatible = "pci14c3,7603"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -95,7 +96,8 @@ wifi@0,0 { compatible = "pci14c3,7662"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts index 8340ca5d28..a9b62b1b28 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts @@ -50,7 +50,8 @@ wifi@0,0 { compatible = "pci14c3,7603"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -59,7 +60,8 @@ wifi@0,0 { compatible = "pci14c3,7662"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi index d05872337b..8f88eb175d 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi @@ -23,12 +23,14 @@ }; &wifi0 { - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; &wifi1 { - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi index 7ce9aea335..7b8c4e8dfd 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi @@ -70,6 +70,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x200>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts index 67ff6ea11e..719d430fd8 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts @@ -35,6 +35,11 @@ }; }; +/* override EEPROM size to 0x4da8 for MT7613 */ +&eeprom_factory_8000 { + reg = <0x8000 0x4da8>; +}; + &partitions { partition@180000 { // size changed against to the common dtsi @@ -49,12 +54,14 @@ }; &wifi0 { - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; &wifi1 { - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi index 1dc91d8b47..3a877e9bec 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi @@ -56,6 +56,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x200>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi index c7d6c574aa..468f9456bf 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi @@ -2,6 +2,11 @@ #include "mt7621_xiaomi_nand_128m.dtsi" +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_8000 { + reg = <0x8000 0x4da8>; +}; + &pcie { status = "okay"; }; @@ -10,7 +15,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; @@ -19,7 +25,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_yuncore_ax820.dts b/target/linux/ramips/dts/mt7621_yuncore_ax820.dts index bbd546f300..bca9498be8 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_ax820.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_ax820.dts @@ -121,6 +121,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + macaddr_factory_e000: macaddr@e000 { compatible = "mac-base"; reg = <0xe000 0x6>; @@ -146,7 +154,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_yuncore_fap640.dts b/target/linux/ramips/dts/mt7621_yuncore_fap640.dts index 8c662b86cd..c61189c4bc 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_fap640.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_fap640.dts @@ -129,8 +129,16 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_factory_0004: macaddr@0004 { - reg = <0x0004 0x6>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; }; macaddr_factory_e006: macaddr@e006 { @@ -156,7 +164,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; @@ -171,7 +180,7 @@ label = "wan"; phy-handle = <ðphy4>; - nvmem-cells = <&macaddr_factory_0004>; + nvmem-cells = <&macaddr_factory_4>; nvmem-cell-names = "mac-address"; }; diff --git a/target/linux/ramips/dts/mt7621_yuncore_fap690.dts b/target/linux/ramips/dts/mt7621_yuncore_fap690.dts index ce6a60215e..caebe0b589 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_fap690.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_fap690.dts @@ -99,8 +99,16 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_factory_0004: macaddr@0004 { - reg = <0x0004 0x6>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; }; }; }; @@ -122,13 +130,14 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; &gmac0 { - nvmem-cells = <&macaddr_factory_0004>; + nvmem-cells = <&macaddr_factory_4>; nvmem-cell-names = "mac-address"; }; diff --git a/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi b/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi index 85dbe2d857..6272b178ec 100644 --- a/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi +++ b/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi @@ -40,6 +40,20 @@ label = "factory"; reg = <0x100000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@180000 { @@ -118,9 +132,8 @@ wlan_5g: wifi@0,0 { reg = <0x0 0 0 0 0>; compatible = "mediatek,mt76"; - - mediatek,mtd-eeprom = <&factory 0x0>; - + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; /* MAC-Address set in userspace */ }; }; diff --git a/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts b/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts index 0cd1f3274c..a283b55c11 100644 --- a/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts +++ b/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts @@ -112,6 +112,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + macaddr_factory_1fdfa: macaddr@1fdfa { reg = <0x1fdfa 0x6>; }; @@ -199,7 +207,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi index ddc3011aab..906ea03fe9 100644 --- a/target/linux/ramips/dts/mt7628an.dtsi +++ b/target/linux/ramips/dts/mt7628an.dtsi @@ -39,7 +39,7 @@ #size-cells = <1>; sysc: syscon@0 { - compatible = "ralink,mt7628-sysc", "syscon"; + compatible = "ralink,mt7628-sysc", "ralink,mt7688-sysc", "syscon"; reg = <0x0 0x100>; #clock-cells = <1>; #reset-cells = <1>; @@ -411,8 +411,8 @@ interrupt-parent = <&cpuintc>; interrupts = <5>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; mediatek,switch = <&esw>; }; @@ -421,8 +421,8 @@ compatible = "mediatek,mt7628-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts b/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts new file mode 100644 index 0000000000..17fa9c0b5a --- /dev/null +++ b/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7628an.dtsi" + +#include +#include +#include + +/ { + model = "TP-Link RE365 v1"; + compatible = "tplink,re365-v1", "mediatek,mt7628an-soc"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = ðernet; + }; + + keys { + compatible = "gpio-keys"; + + button-led { + label = "led"; + gpios = <&gpio 44 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-power { + label = "power"; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-reset { + label = "reset"; + gpios = <&gpio 37 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-wps { + label = "wps"; + gpios = <&gpio 38 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + }; + + led_power: led-power { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 39 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + + led-rssi-bad { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; + }; + + led-rssi-good { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; + }; + + led-wlan2g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <2>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-wlan5g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <5>; + gpios = <&gpio 40 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; + + virtual_flash { + compatible = "mtd-concat"; + devices = <&fwconcat0>, <&fwconcat1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "tplink,firmware"; + label = "firmware"; + reg = <0x0 0x0>; + }; + }; + }; +}; + +ðernet { + nvmem-cells = <&macaddr_config_10008 0>; + nvmem-cell-names = "mac-address"; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + mt76@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + nvmem-cells = <&eeprom_radio_8000>, <&macaddr_config_10008 2>; + nvmem-cell-names = "eeprom", "mac-address"; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + fwconcat0: partition@20000 { + label = "fwconcat0"; + reg = <0x20000 0x5e0000>; + }; + + partition@600000 { + label = "config"; + reg = <0x600000 0x50000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_config_10008: macaddr@10008 { + compatible = "mac-base"; + reg = <0x10008 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + fwconcat1: partition@650000 { + label = "fwconcat1"; + reg = <0x650000 0x1a0000>; + }; + + partition@7f0000 { + label = "radio"; + reg = <0x7f0000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_radio_8000: eeprom@8000 { + reg = <0x8000 0x200>; + }; + }; + }; + }; + }; +}; + +&state_default { + gpio { + groups = "refclk", "wdt", "p0led_an", "p1led_an", "p2led_an", "p3led_an", + "p4led_an"; + function = "gpio"; + }; +}; + +&wmac { + status = "okay"; + + nvmem-cells = <&eeprom_radio_0>, <&macaddr_config_10008 1>; + nvmem-cell-names = "eeprom", "mac-address"; +}; diff --git a/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts b/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts index 3bdb06cec9..01c8bb942a 100644 --- a/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts +++ b/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts @@ -49,9 +49,6 @@ keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - reset { label = "reset"; gpios = <&gpio 11 GPIO_ACTIVE_LOW>; diff --git a/target/linux/ramips/dts/rt3050.dtsi b/target/linux/ramips/dts/rt3050.dtsi index 4d70773ed1..30a3f898cd 100644 --- a/target/linux/ramips/dts/rt3050.dtsi +++ b/target/linux/ramips/dts/rt3050.dtsi @@ -40,7 +40,7 @@ #size-cells = <1>; sysc: syscon@0 { - compatible = "ralink,rt3050-sysc", "syscon"; + compatible = "ralink,rt3050-sysc", "ralink,rt3052-sysc", "syscon"; reg = <0x0 0x100>; #clock-cells = <1>; #reset-cells = <1>; @@ -301,8 +301,8 @@ clocks = <&sysc 11>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; interrupt-parent = <&cpuintc>; interrupts = <5>; @@ -314,8 +314,8 @@ compatible = "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/rt3352.dtsi b/target/linux/ramips/dts/rt3352.dtsi index 0ac3227ce0..b4829cb1b1 100644 --- a/target/linux/ramips/dts/rt3352.dtsi +++ b/target/linux/ramips/dts/rt3352.dtsi @@ -319,8 +319,8 @@ clocks = <&sysc 12>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; interrupt-parent = <&cpuintc>; interrupts = <5>; @@ -332,8 +332,8 @@ compatible = "ralink,rt3352-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/rt3662_engenius_esr600h.dts b/target/linux/ramips/dts/rt3662_engenius_esr600h.dts index 6770e4cc9a..e142fe5347 100644 --- a/target/linux/ramips/dts/rt3662_engenius_esr600h.dts +++ b/target/linux/ramips/dts/rt3662_engenius_esr600h.dts @@ -161,9 +161,9 @@ &pci1 { status = "okay"; - wifi@0,1,0 { + wifi@0,0 { compatible = "pci1814,3091"; - reg = <0x0 1 0 0 0>; + reg = <0x10000 0 0 0 0>; ralink,5ghz = <0>; nvmem-cells = <&eeprom_factory_8000>; nvmem-cell-names = "eeprom"; diff --git a/target/linux/ramips/dts/rt3883.dtsi b/target/linux/ramips/dts/rt3883.dtsi index 148922e8b9..8c76eb6631 100644 --- a/target/linux/ramips/dts/rt3883.dtsi +++ b/target/linux/ramips/dts/rt3883.dtsi @@ -399,7 +399,7 @@ 0x9000 0 0 4 &pciintc 19 >; - pci1: pci@1 { + pci1: pci@1,0 { reg = <0x0800 0 0 0 0>; device_type = "pci"; #interrupt-cells = <1>; @@ -421,6 +421,7 @@ #address-cells = <3>; #size-cells = <2>; + interrupt-controller; status = "disabled"; }; @@ -430,6 +431,7 @@ #address-cells = <3>; #size-cells = <2>; + interrupt-controller; status = "disabled"; }; }; diff --git a/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi b/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi index 4a64d8a7fe..17c982a314 100644 --- a/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi +++ b/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi @@ -102,7 +102,7 @@ &pci1 { status = "okay"; - wifi@1,0 { + wifi@0,0 { compatible = "pci1814,3091"; reg = <0x10000 0 0 0 0>; ralink,5ghz = <0>; diff --git a/target/linux/ramips/dts/rt5350.dtsi b/target/linux/ramips/dts/rt5350.dtsi index 9bbbc611ed..30f6435842 100644 --- a/target/linux/ramips/dts/rt5350.dtsi +++ b/target/linux/ramips/dts/rt5350.dtsi @@ -340,8 +340,8 @@ clocks = <&sysc 12>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; interrupt-parent = <&cpuintc>; interrupts = <5>; @@ -353,8 +353,8 @@ compatible = "ralink,rt5350-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c index 47471eb197..5a36652a11 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c @@ -237,7 +237,6 @@ struct rt305x_esw { int led_frequency; struct esw_vlan vlans[RT305X_ESW_NUM_VLANS]; struct esw_port ports[RT305X_ESW_NUM_PORTS]; - struct reset_control *rst_esw; struct reset_control *rst_ephy; }; @@ -261,18 +260,6 @@ static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, __raw_writel(t | val, esw->base + reg); } -static void esw_reset(struct rt305x_esw *esw) -{ - if (!esw->rst_esw) - return; - - reset_control_assert(esw->rst_esw); - usleep_range(60, 120); - reset_control_deassert(esw->rst_esw); - /* the esw takes long to reset otherwise the board hang */ - msleep(10); -} - static void esw_reset_ephy(struct rt305x_esw *esw) { if (!esw->rst_ephy) @@ -466,8 +453,6 @@ static void esw_hw_init(struct rt305x_esw *esw) u8 port_disable = 0; u8 port_map = RT305X_ESW_PMAP_LLLLLL; - esw_reset(esw); - /* vodoo from original driver */ esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2); @@ -1441,12 +1426,11 @@ static int esw_probe(struct platform_device *pdev) if (reg_init) esw->reg_led_source = be32_to_cpu(*reg_init); - esw->rst_esw = devm_reset_control_get(&pdev->dev, "esw"); - if (IS_ERR(esw->rst_esw)) - esw->rst_esw = NULL; - esw->rst_ephy = devm_reset_control_get(&pdev->dev, "ephy"); - if (IS_ERR(esw->rst_ephy)) + esw->rst_ephy = devm_reset_control_get_exclusive(&pdev->dev, "ephy"); + if (IS_ERR(esw->rst_ephy)) { + dev_err(esw->dev, "failed to get EPHY reset: %pe\n", esw->rst_ephy); esw->rst_ephy = NULL; + } spin_lock_init(&esw->reg_rw_lock); platform_set_drvdata(pdev, esw); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c index 5732c28536..a3abf30c71 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c @@ -161,7 +161,7 @@ static void fe_get_strings(struct net_device *dev, u32 stringset, u8 *data) { switch (stringset) { case ETH_SS_STATS: - memcpy(data, *fe_gdma_str, sizeof(fe_gdma_str)); + ethtool_puts(&data, *fe_gdma_str); break; } } diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c index 84b6e305a4..dcaff04db1 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c @@ -61,6 +61,17 @@ static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv) return IRQ_HANDLED; } +static void gsw_reset_ephy(struct mt7620_gsw *gsw) +{ + if (!gsw->rst_ephy) + return; + + reset_control_assert(gsw->rst_ephy); + usleep_range(10, 20); + reset_control_deassert(gsw->rst_ephy); + usleep_range(10, 20); +} + static void mt7620_ephy_init(struct mt7620_gsw *gsw) { u32 i; @@ -79,7 +90,7 @@ static void mt7620_ephy_init(struct mt7620_gsw *gsw) mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_GPC1) | (gsw->ephy_base << 16), GSW_REG_GPC1); - fe_reset(MT7620A_RESET_EPHY); + gsw_reset_ephy(gsw); pr_info("gsw: ephy base address: %d\n", gsw->ephy_base); } @@ -263,6 +274,12 @@ static int mt7620_gsw_probe(struct platform_device *pdev) gsw->irq = platform_get_irq(pdev, 0); + gsw->rst_ephy = devm_reset_control_get_exclusive(&pdev->dev, "ephy"); + if (IS_ERR(gsw->rst_ephy)) { + dev_err(gsw->dev, "failed to get EPHY reset: %pe\n", gsw->rst_ephy); + gsw->rst_ephy = NULL; + } + platform_set_drvdata(pdev, gsw); return 0; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h index cb5d098e9c..12cab39b77 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h @@ -12,6 +12,8 @@ * Copyright (C) 2013-2015 Michael Lee */ +#include + #ifndef _RALINK_GSW_MT7620_H__ #define _RALINK_GSW_MT7620_H__ @@ -90,6 +92,7 @@ enum { struct mt7620_gsw { struct device *dev; + struct reset_control *rst_ephy; void __iomem *base; int irq; bool ephy_disable; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c index b79b348938..c741c85f4a 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c @@ -61,8 +61,6 @@ #define NEXT_TX_DESP_IDX(X) (((X) + 1) & (ring->tx_ring_size - 1)) #define NEXT_RX_DESP_IDX(X) (((X) + 1) & (ring->rx_ring_size - 1)) -#define SYSC_REG_RSTCTRL 0x34 - static int fe_msg_level = -1; module_param_named(msg_level, fe_msg_level, int, 0); MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); @@ -127,29 +125,15 @@ void fe_m32(struct fe_priv *eth, u32 clear, u32 set, unsigned reg) spin_unlock(ð->page_lock); } -void fe_reset(u32 reset_bits) +static void fe_reset_fe(struct fe_priv *priv) { - u32 t; - - t = rt_sysc_r32(SYSC_REG_RSTCTRL); - t |= reset_bits; - rt_sysc_w32(t, SYSC_REG_RSTCTRL); - usleep_range(10, 20); - - t &= ~reset_bits; - rt_sysc_w32(t, SYSC_REG_RSTCTRL); - usleep_range(10, 20); -} - -void fe_reset_fe(struct fe_priv *priv) -{ - if (!priv->rst_fe) + if (!priv->resets) return; - reset_control_assert(priv->rst_fe); - usleep_range(60, 120); - reset_control_deassert(priv->rst_fe); + reset_control_assert(priv->resets); usleep_range(60, 120); + reset_control_deassert(priv->resets); + usleep_range(1000, 1200); } static inline void fe_int_disable(u32 mask) @@ -1366,10 +1350,7 @@ static int __init fe_init(struct net_device *dev) struct device_node *port; int err; - if (priv->soc->reset_fe) - priv->soc->reset_fe(priv); - else - fe_reset_fe(priv); + fe_reset_fe(priv); if (priv->soc->switch_init) { err = priv->soc->switch_init(priv); @@ -1595,9 +1576,11 @@ static int fe_probe(struct platform_device *pdev) priv = netdev_priv(netdev); spin_lock_init(&priv->page_lock); - priv->rst_fe = devm_reset_control_get(&pdev->dev, "fe"); - if (IS_ERR(priv->rst_fe)) - priv->rst_fe = NULL; + priv->resets = devm_reset_control_array_get_exclusive(&pdev->dev); + if (IS_ERR(priv->resets)) { + dev_err(&pdev->dev, "Failed to get resets for FE and ESW cores: %pe\n", priv->resets); + priv->resets = NULL; + } if (soc->init_data) soc->init_data(soc, netdev); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h index 968db366cf..7b291ff43e 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h @@ -157,10 +157,6 @@ enum fe_work_flag { #define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C) #define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10) -#define MT7620A_RESET_FE BIT(21) -#define MT7620A_RESET_ESW BIT(23) -#define MT7620A_RESET_EPHY BIT(24) - #define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) #define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04) #define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08) @@ -382,7 +378,6 @@ struct fe_soc_data { const u16 *reg_table; void (*init_data)(struct fe_soc_data *data, struct net_device *netdev); - void (*reset_fe)(struct fe_priv *priv); void (*set_mac)(struct fe_priv *priv, unsigned char *mac); int (*fwd_config)(struct fe_priv *priv); void (*tx_dma)(struct fe_tx_dma *txd); @@ -497,8 +492,7 @@ struct fe_priv { struct work_struct pending_work; DECLARE_BITMAP(pending_flags, FE_FLAG_MAX); - struct reset_control *rst_ppe; - struct reset_control *rst_fe; + struct reset_control *resets; struct mtk_foe_entry *foe_table; dma_addr_t foe_table_phys; struct flow_offload __rcu **foe_flow_table; @@ -517,9 +511,6 @@ void fe_fwd_config(struct fe_priv *priv); void fe_reg_w32(u32 val, enum fe_reg reg); u32 fe_reg_r32(enum fe_reg reg); -void fe_reset(u32 reset_bits); -void fe_reset_fe(struct fe_priv *priv); - static inline void *priv_netdev(struct fe_priv *priv) { return (char *)priv - ALIGN(sizeof(struct net_device), NETDEV_ALIGN); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c index a4b2908d59..172dda11b7 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c @@ -286,11 +286,6 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) } } -static void mt7620_fe_reset(struct fe_priv *priv) -{ - fe_reset(MT7620A_RESET_FE | MT7620A_RESET_ESW); -} - static void mt7620_rxcsum_config(bool enable) { if (enable) @@ -348,7 +343,6 @@ static void mt7620_init_data(struct fe_soc_data *data, static struct fe_soc_data mt7620_data = { .init_data = mt7620_init_data, - .reset_fe = mt7620_fe_reset, .set_mac = mt7620_set_mac, .fwd_config = mt7620_fwd_config, .tx_dma = mt7620_tx_dma, diff --git a/target/linux/ramips/image/lzma-loader/src/board.c b/target/linux/ramips/image/lzma-loader/src/board.c index ae9da38073..de02f58b9f 100644 --- a/target/linux/ramips/image/lzma-loader/src/board.c +++ b/target/linux/ramips/image/lzma-loader/src/board.c @@ -11,22 +11,39 @@ */ #include +#include + +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 + +#define _ATYPE_ __PTRDIFF_TYPE__ +#define _ATYPE32_ int + +#define _ACAST32_ (_ATYPE_)(_ATYPE32_) + +#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) + +#define KSEG0ADDR(a) (CPHYSADDR(a) | KSEG0) +#define KSEG1ADDR(a) (CPHYSADDR(a) | KSEG1) + +#define UART_LSR_THRE 0x20 +#define UART_LSR_TEMT 0x40 #if defined(SOC_MT7620) || defined(SOC_RT3883) -#define UART_BASE 0xb0000c00 +#define UART_BASE KSEG1ADDR(0x10000c00) #define UART_THR (UART_BASE + 0x04) #define UART_LSR (UART_BASE + 0x1c) -#define UART_LSR_THRE_MASK 0x40 +#define UART_LSR_MASK UART_LSR_TEMT #elif defined(SOC_MT7621) -#define UART_BASE 0xbe000c00 +#define UART_BASE KSEG1ADDR(0x1e000c00) #define UART_THR (UART_BASE + 0x00) #define UART_LSR (UART_BASE + 0x14) -#define UART_LSR_THRE_MASK 0x20 +#define UART_LSR_MASK UART_LSR_THRE #elif defined(SOC_RT305X) -#define UART_BASE 0x10000500 +#define UART_BASE KSEG1ADDR(0x10000c00) #define UART_THR (UART_BASE + 0x04) #define UART_LSR (UART_BASE + 0x1c) -#define UART_LSR_THRE_MASK 0x20 +#define UART_LSR_MASK UART_LSR_THRE #else #error "Unsupported SOC..." #endif @@ -42,7 +59,7 @@ void board_init(void) void board_putc(int ch) { - while ((READREG(UART_LSR) & UART_LSR_THRE_MASK) == 0); + while ((READREG(UART_LSR) & UART_LSR_MASK) == 0); WRITEREG(UART_THR, ch); - while ((READREG(UART_LSR) & UART_LSR_THRE_MASK) == 0); + while ((READREG(UART_LSR) & UART_LSR_MASK) == 0); } diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 2c25b1ab28..ab1b829ba0 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1093,6 +1093,8 @@ define Device/etisalat_s3 SERCOMM_SWVER := 4009 DEVICE_VENDOR := Etisalat DEVICE_MODEL := S3 + DEVICE_ALT0_VENDOR := Sercomm + DEVICE_ALT0_MODEL := S3 DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615-firmware kmod-usb3 endef TARGET_DEVICES += etisalat_s3 diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk index 8a6bccfba6..9a458d38f3 100644 --- a/target/linux/ramips/image/mt76x8.mk +++ b/target/linux/ramips/image/mt76x8.mk @@ -666,6 +666,18 @@ define Device/tplink_re305-v3 endef TARGET_DEVICES += tplink_re305-v3 +define Device/tplink_re365-v1 + $(Device/tplink-safeloader) + DEVICE_MODEL := RE365 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-mt76x2 + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size | append-metadata + IMAGE_SIZE := 7680k + KERNEL_SIZE := 6016k + TPLINK_BOARD_ID := RE365 +endef +TARGET_DEVICES += tplink_re365-v1 + define Device/tplink_tl-mr3020-v3 $(Device/tplink-v2) IMAGE_SIZE := 7808k diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index 51afb9cf41..1061de6f44 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -48,10 +48,10 @@ rostelecom,rt-sf-1) ;; beeline,smartbox-pro|\ wifire,s1500-nbn) - ucidef_set_led_netdev "lan1" "lan1" "green:lan1" "lan1" "link tx rx" - ucidef_set_led_netdev "lan2" "lan2" "green:lan2" "lan2" "link tx rx" - ucidef_set_led_netdev "lan3" "lan3" "green:lan3" "lan3" "link tx rx" - ucidef_set_led_netdev "lan4" "lan4" "green:lan4" "lan4" "link tx rx" + ucidef_set_led_netdev "lan1" "lan1" "green:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan2" "lan2" "green:lan-2" "lan2" "link tx rx" + ucidef_set_led_netdev "lan3" "lan3" "green:lan-3" "lan3" "link tx rx" + ucidef_set_led_netdev "lan4" "lan4" "green:lan-4" "lan4" "link tx rx" ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx" ;; belkin,rt1800) @@ -202,9 +202,9 @@ tplink,deco-m4r-v4) ucidef_set_led_netdev "lan" "LAN" "green:lan" "br-lan" ;; tplink,ec330-g5u-v1) - ucidef_set_led_netdev "lan" "Ethernet" "blue:ethernet" "br-lan" "link tx rx" - ucidef_set_led_netdev "wan" "Internet" "blue:internet" "wan" "link tx rx" - ucidef_set_led_netdev "wan-off" "Internet-off" "amber:internet" "wan" "link" + ucidef_set_led_netdev "lan" "Ethernet" "blue:lan" "br-lan" "link tx rx" + ucidef_set_led_netdev "wan" "Internet" "blue:wan" "wan" "link tx rx" + ucidef_set_led_netdev "wan-off" "Internet-off" "amber:wan" "wan" "link" ;; tplink,re350-v1) ucidef_set_led_netdev "wifi2g" "Wifi 2.4G" "blue:wifi2G" "wlan0" diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds index c4301737b2..5a0e0ab214 100644 --- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds @@ -91,6 +91,9 @@ tplink,tl-mr3020-v3|\ tplink,tl-wa801nd-v5) ucidef_set_led_netdev "lan" "lan" "green:lan" "eth0" ;; +tplink,re365-v1) + ucidef_set_led_netdev "lan" "lan" "blue:lan" "eth0" + ;; tplink,tl-mr3420-v5|\ tplink,tl-wr840n-v4|\ tplink,tl-wr842n-v5) diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network index fe3ac9193f..63abb14d13 100644 --- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network @@ -27,6 +27,7 @@ ramips_setup_interfaces() tplink,re220-v2|\ tplink,re305-v1|\ tplink,re305-v3|\ + tplink,re365-v1|\ tplink,tl-wr802n-v4|\ tplink,tl-wa801nd-v5|\ tplink,tl-wr902ac-v4|\ diff --git a/target/linux/ramips/mt76x8/target.mk b/target/linux/ramips/mt76x8/target.mk index 862736cb2f..cfc2655cac 100644 --- a/target/linux/ramips/mt76x8/target.mk +++ b/target/linux/ramips/mt76x8/target.mk @@ -4,7 +4,7 @@ SUBTARGET:=mt76x8 BOARDNAME:=MT76x8 based boards -FEATURES+=usb ramdisk +FEATURES+=usb ramdisk small_flash CPU_TYPE:=24kc DEFAULT_PACKAGES += kmod-mt7603 wpad-basic-mbedtls swconfig diff --git a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch index 437c761132..1262e9498d 100644 --- a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch +++ b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch @@ -33,7 +33,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c phy_led_trigger_change_speed(phydev); } -@@ -563,7 +563,7 @@ int phy_start_cable_test(struct phy_devi +@@ -591,7 +591,7 @@ int phy_start_cable_test(struct phy_devi goto out; /* Mark the carrier down until the test is complete */ @@ -42,7 +42,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c netif_testing_on(dev); err = phydev->drv->cable_test_start(phydev); -@@ -634,7 +634,7 @@ int phy_start_cable_test_tdr(struct phy_ +@@ -662,7 +662,7 @@ int phy_start_cable_test_tdr(struct phy_ goto out; /* Mark the carrier down until the test is complete */ @@ -51,7 +51,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c netif_testing_on(dev); err = phydev->drv->cable_test_tdr_start(phydev, config); -@@ -706,7 +706,7 @@ static int phy_check_link_status(struct +@@ -734,7 +734,7 @@ static int phy_check_link_status(struct phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; @@ -60,7 +60,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c } return 0; -@@ -1192,7 +1192,7 @@ void phy_state_machine(struct work_struc +@@ -1220,7 +1220,7 @@ void phy_state_machine(struct work_struc case PHY_HALTED: if (phydev->link) { phydev->link = 0; @@ -95,7 +95,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c phydev->mii_ts->link_state(phydev->mii_ts, phydev); --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -1370,7 +1370,8 @@ void phylink_destroy(struct phylink *pl) +@@ -1373,7 +1373,8 @@ void phylink_destroy(struct phylink *pl) } EXPORT_SYMBOL_GPL(phylink_destroy); @@ -107,7 +107,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c bool tx_pause, rx_pause; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -706,7 +706,7 @@ struct phy_device { +@@ -716,7 +716,7 @@ struct phy_device { u8 mdix; u8 mdix_ctrl; diff --git a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch index 5205a8f936..fc7873a01b 100644 --- a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch +++ b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch @@ -11,7 +11,7 @@ Signed-off-by: John Crispin --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c -@@ -706,7 +706,10 @@ static int phy_check_link_status(struct +@@ -734,7 +734,10 @@ static int phy_check_link_status(struct phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; @@ -23,7 +23,7 @@ Signed-off-by: John Crispin } return 0; -@@ -1192,7 +1195,10 @@ void phy_state_machine(struct work_struc +@@ -1220,7 +1223,10 @@ void phy_state_machine(struct work_struc case PHY_HALTED: if (phydev->link) { phydev->link = 0; @@ -37,7 +37,7 @@ Signed-off-by: John Crispin break; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -622,6 +622,7 @@ struct phy_device { +@@ -630,6 +630,7 @@ struct phy_device { unsigned downshifted_rate:1; unsigned is_on_sfp_module:1; unsigned mac_managed_pm:1; diff --git a/target/linux/realtek/base-files/etc/board.d/02_network b/target/linux/realtek/base-files/etc/board.d/02_network index 4a5fe7666c..fb9c28d794 100644 --- a/target/linux/realtek/base-files/etc/board.d/02_network +++ b/target/linux/realtek/base-files/etc/board.d/02_network @@ -91,6 +91,9 @@ hpe,1920-8g-poe-180w) netgear,gs110tpp-v1) ucidef_set_poe 130 "$lan_list" "lan9 lan10" ;; +netgear,gs110tup-v1) + ucidef_set_poe 240 "$lan_list" "lan9 lan10" + ;; netgear,gs310tp-v1) ucidef_set_poe 55 "$lan_list" "lan9 lan10" ;; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi index 5e587f278d..aca1a14774 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi @@ -58,6 +58,62 @@ }; }; +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x00e0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0x00e0000 0x0010000>; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0x00f0000 0x0010000>; + }; + + partition@100000 { + label = "jffs"; + reg = <0x0100000 0x0100000>; + read-only; + }; + + partition@200000 { + label = "jffs2"; + reg = <0x0200000 0x0100000>; + read-only; + }; + + firmware: partition@300000 { + label = "firmware"; + compatible = "openwrt,uimage", "denx,uimage"; + reg = <0x0300000 0x0e80000>; + }; + + partition@1180000 { + label = "runtime2"; + reg = <0x1180000 0x0e80000>; + read-only; + }; + }; + }; +}; + &switch0 { ports { #address-cells = <1>; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi deleted file mode 100644 index fd44543bb4..0000000000 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "rtl8380_netgear_gigabit.dtsi" - -&spi0 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <50000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "u-boot"; - reg = <0x0000000 0x00e0000>; - read-only; - }; - - partition@e0000 { - label = "u-boot-env"; - reg = <0x00e0000 0x0010000>; - }; - - partition@f0000 { - label = "u-boot-env2"; - reg = <0x00f0000 0x0010000>; - }; - - partition@100000 { - label = "jffs"; - reg = <0x0100000 0x0100000>; - read-only; - }; - - partition@200000 { - label = "jffs2"; - reg = <0x0200000 0x0100000>; - read-only; - }; - - partition@300000 { - label = "firmware"; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x4e474520>; - reg = <0x0300000 0x0e80000>; - }; - - partition@1180000 { - label = "runtime2"; - reg = <0x1180000 0x0e80000>; - read-only; - }; - }; - }; -}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi deleted file mode 100644 index 0ade665c98..0000000000 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "rtl8380_netgear_gigabit.dtsi" - -&spi0 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <50000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "u-boot"; - reg = <0x0000000 0x00e0000>; - read-only; - }; - - partition@e0000 { - label = "u-boot-env"; - reg = <0x00e0000 0x0010000>; - }; - - partition@f0000 { - label = "u-boot-env2"; - reg = <0x00f0000 0x0010000>; - }; - - partition@100000 { - label = "jffs"; - reg = <0x0100000 0x0100000>; - read-only; - }; - - partition@200000 { - label = "jffs2"; - reg = <0x0200000 0x0100000>; - read-only; - }; - - partition@300000 { - label = "firmware"; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x4e474335>; - reg = <0x0300000 0x0e80000>; - }; - - partition@1180000 { - label = "runtime2"; - reg = <0x1180000 0x0e80000>; - read-only; - }; - }; - }; -}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts index e149834d44..c1d72b880b 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_1xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" #include @@ -33,3 +33,7 @@ }; }; }; + +&firmware { + openwrt,ih-magic = <0x4e474520>; +}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts index b61af62ea5..599b2e3b51 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_1xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" #include / { @@ -40,6 +40,10 @@ }; }; +&firmware { + openwrt,ih-magic = <0x4e474520>; +}; + &uart1 { status = "okay"; }; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tup-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tup-v1.dts new file mode 100644 index 0000000000..76653fa210 --- /dev/null +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tup-v1.dts @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit.dtsi" +#include + +/ { + compatible = "netgear,gs110tup-v1", "realtek,rtl838x-soc"; + model = "Netgear GS110TUP v1"; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_blue; + }; + + leds { + compatible = "gpio-leds"; + + led_status_red: led-0 { + label = "red:status"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 31 GPIO_ACTIVE_LOW>; + }; + + led_status_green: led-1 { + label = "green:status"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 32 GPIO_ACTIVE_LOW>; + }; + + led_status_blue: led-2 { + label = "blue:status"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 34 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&firmware { + openwrt,ih-magic = <0x4e474720>; +}; + +&uart1 { + status = "okay"; +}; + +&mdio { + EXTERNAL_PHY(16) + EXTERNAL_PHY(24) +}; + +&switch0 { + ports { + SWITCH_PORT(16, 9, qsgmii) + SWITCH_SFP_PORT(24, 10, rgmii-id) + }; +}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts index cd69e80186..5cf3ca0c81 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_3xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" #include @@ -33,3 +33,7 @@ }; }; }; + +&firmware { + openwrt,ih-magic = <0x4e474335>; +}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts index dacd504ac4..a6f7181c11 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_3xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" / { compatible = "netgear,gs310tp-v1", "realtek,rtl838x-soc"; @@ -8,6 +8,10 @@ }; +&firmware { + openwrt,ih-magic = <0x4e474335>; +}; + &uart1 { status = "okay"; }; diff --git a/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts b/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts index 16934ede3b..1aef88afd4 100644 --- a/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts +++ b/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts @@ -7,6 +7,42 @@ compatible = "d-link,dgs-1210-10p", "realtek,rtl838x-soc"; model = "D-Link DGS-1210-10P"; + /* i2c of the left SFP cage: port 9 */ + i2c0: i2c-gpio-0 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp0: sfp-p9 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + los-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + + /* i2c of the right SFP cage: port 10 */ + i2c1: i2c-gpio-1 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp1: sfp-p10 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + los-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; + }; + keys { compatible = "gpio-keys-polled"; poll-interval = <20>; @@ -86,8 +122,24 @@ SWITCH_PORT(13, 6, internal) SWITCH_PORT(14, 7, internal) SWITCH_PORT(15, 8, internal) - SWITCH_SFP_PORT(24, 9, rgmii-id) - SWITCH_SFP_PORT(26, 10, rgmii-id) + + port@24 { + reg = <24>; + label = "lan9"; + phy-handle = <&phy24>; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp0>; + }; + + port@26 { + reg = <26>; + label = "lan10"; + phy-handle = <&phy26>; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp1>; + }; port@28 { ethernet = <ðernet0>; diff --git a/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts b/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts index 750af3e94f..5a7ed276bf 100644 --- a/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts +++ b/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts @@ -107,7 +107,8 @@ compatible = "realtek,rtl838x-mdio"; #address-cells = <1>; #size-cells = <0>; - reset-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + // Switch doesn't come back properly after a reset so don't. + // reset-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; /* External phy RTL8218B #1 */ EXTERNAL_PHY(0) @@ -190,7 +191,7 @@ SWITCH_PORT(7, 8, qsgmii) SWITCH_PORT(8, 9, qsgmii) - SWITCH_PORT(9, 0, qsgmii) + SWITCH_PORT(9, 10, qsgmii) SWITCH_PORT(10, 11, qsgmii) SWITCH_PORT(11, 12, qsgmii) SWITCH_PORT(12, 13, qsgmii) diff --git a/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts b/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts index 0fe8f1997e..98ac08b26a 100644 --- a/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts +++ b/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts @@ -66,10 +66,10 @@ compatible = "realtek,rtl9300-leds"; active-low; - led_set0 = <0x0000 0xffff 0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps + led_set0 = <0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps led_set1 = <0x0a0b 0x0a28 0x0a82 0x0a0b>; // LED set 1: (10G, 5G, 2.5G) (2.5G, 1G) // (5G, 10/100) (10G, 5G, 2.5G) - led_set2 = <0x0000 0xffff 0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit + led_set2 = <0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit }; }; diff --git a/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h b/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h index d9c0b311ae..8ea580f3d1 100644 --- a/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h +++ b/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h @@ -291,7 +291,7 @@ #define RTL838X_LED_P_EN_CTRL (0xA008) /* LED control by software */ -#define RTL838X_LED_SW_CTRL (0x0128) +#define RTL838X_LED_SW_CTRL (0xA00C) #define RTL839X_LED_SW_CTRL (0xA00C) #define RTL838X_LED_SW_P_EN_CTRL (0xA010) #define RTL839X_LED_SW_P_EN_CTRL (0x012C) @@ -302,6 +302,7 @@ #define RTL838X_LED2_SW_P_EN_CTRL (0xA018) #define RTL839X_LED2_SW_P_EN_CTRL (0x0134) #define RTL838X_LED_SW_P_CTRL (0xA01C) +#define RTL838X_LED_SW_P_CTRL_PORT(p) (RTL838X_LED_SW_P_CTRL + (((p) << 2))) #define RTL839X_LED_SW_P_CTRL (0x0144) #define RTL839X_MAC_EFUSE_CTRL (0x02ac) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c index 0434312afc..221428cc77 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c @@ -271,7 +271,7 @@ int write_phy(u32 port, u32 page, u32 reg, u32 val) static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) { struct device *dev = priv->dev; - struct device_node *dn, *phy_node, *mii_np = dev->of_node; + struct device_node *dn, *phy_node, *led_node, *mii_np = dev->of_node; struct mii_bus *bus; int ret; u32 pn; @@ -325,9 +325,12 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) return -ENODEV; } + led_node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); + for_each_node_by_name(dn, "port") { phy_interface_t interface; u32 led_set; + char led_set_str[16] = {0}; if (!of_device_is_available(dn)) continue; @@ -355,9 +358,18 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) if (interface == PHY_INTERFACE_MODE_10GBASER) priv->ports[pn].is10G = true; - if (of_property_read_u32(dn, "led-set", &led_set)) - led_set = 0; - priv->ports[pn].led_set = led_set; + priv->ports[pn].leds_on_this_port = 0; + if (led_node) { + if (of_property_read_u32(dn, "led-set", &led_set)) + led_set = 0; + priv->ports[pn].led_set = led_set; + sprintf(led_set_str, "led_set%d", led_set); + priv->ports[pn].leds_on_this_port = of_property_count_u32_elems(led_node, led_set_str); + if (priv->ports[pn].leds_on_this_port > 4) { + dev_err(priv->dev, "led_set %d for port %d configuration is invalid\n", led_set, pn); + return -ENODEV; + } + } /* Check for the integrated SerDes of the RTL8380M first */ if (of_property_read_bool(phy_node, "phy-is-integrated") diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c index 1c32d47c6f..92d6932dc5 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c @@ -8,16 +8,6 @@ #define RTL838X_DRIVER_NAME "rtl838x" -#define RTL8380_LED_GLB_CTRL (0xA000) -#define RTL8380_LED_MODE_SEL (0x1004) -#define RTL8380_LED_MODE_CTRL (0xA004) -#define RTL8380_LED_P_EN_CTRL (0xA008) -#define RTL8380_LED_SW_CTRL (0xA00C) -#define RTL8380_LED0_SW_P_EN_CTRL (0xA010) -#define RTL8380_LED1_SW_P_EN_CTRL (0xA014) -#define RTL8380_LED2_SW_P_EN_CTRL (0xA018) -#define RTL8380_LED_SW_P_CTRL(p) (0xA01C + (((p) << 2))) - #define RTL8390_LED_GLB_CTRL (0x00E4) #define RTL8390_LED_SET_2_3_CTRL (0x00E8) #define RTL8390_LED_SET_0_1_CTRL (0x00EC) @@ -520,28 +510,28 @@ static int rtl838x_dbgfs_leds(struct dentry *parent, struct rtl838x_switch_priv if (priv->family_id == RTL8380_FAMILY_ID) { debugfs_create_x32("led_glb_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_GLB_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_GLB_CTRL)); debugfs_create_x32("led_mode_sel", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_SEL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_MODE_SEL)); debugfs_create_x32("led_mode_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_MODE_CTRL)); debugfs_create_x32("led_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_P_EN_CTRL)); debugfs_create_x32("led_sw_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_SW_CTRL)); debugfs_create_x32("led0_sw_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED0_SW_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED0_SW_P_EN_CTRL)); debugfs_create_x32("led1_sw_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED1_SW_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED1_SW_P_EN_CTRL)); debugfs_create_x32("led2_sw_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED2_SW_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED2_SW_P_EN_CTRL)); for (int p = 0; p < 28; p++) { char led_sw_p_ctrl_name[20]; snprintf(led_sw_p_ctrl_name, sizeof(led_sw_p_ctrl_name), "led_sw_p_ctrl.%02d", p); debugfs_create_x32(led_sw_p_ctrl_name, 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_P_CTRL(p))); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_SW_P_CTRL_PORT(p))); } } else if (priv->family_id == RTL8390_FAMILY_ID) { char port_led_name[20]; diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index d246e60cb2..a5b8ccea1c 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -137,9 +137,9 @@ static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv) priv->r->vlan_set_tagged(i, &info); /* reset PVIDs; defaults to 1 on reset */ - for (int i = 0; i <= priv->ds->num_ports; i++) { - priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 0); - priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 0); + for (int i = 0; i <= priv->cpu_port; i++) { + priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 1); + priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 1); priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_INNER, PBVLAN_MODE_UNTAG_AND_PRITAG); priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_OUTER, PBVLAN_MODE_UNTAG_AND_PRITAG); } @@ -870,6 +870,8 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port, if (state->duplex == DUPLEX_FULL) reg |= RTL930X_DUPLEX_MODE; + else + reg &= ~RTL930X_DUPLEX_MODE; /* Clear duplex bit otherwise */ if (priv->ports[port].phy_is_integrated) reg &= ~RTL930X_FORCE_EN; /* Clear MAC_FORCE_EN to allow SDS-MAC link */ @@ -944,8 +946,7 @@ static void rtl83xx_get_strings(struct dsa_switch *ds, return; for (int i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++) - strncpy(data + i * ETH_GSTRING_LEN, rtl83xx_mib[i].name, - ETH_GSTRING_LEN); + ethtool_puts(&data, rtl83xx_mib[i].name); } static void rtl83xx_get_ethtool_stats(struct dsa_switch *ds, int port, @@ -1358,10 +1359,15 @@ static int rtl83xx_vlan_filtering(struct dsa_switch *ds, int port, * 2: Trap packet to CPU port * The Egress filter used 1 bit per state (0: DISABLED, 1: ENABLED) */ - if (port != priv->cpu_port) + if (port != priv->cpu_port) { priv->r->set_vlan_igr_filter(port, IGR_DROP); + priv->r->set_vlan_egr_filter(port, EGR_ENABLE); + } + else { + priv->r->set_vlan_igr_filter(port, IGR_TRAP); + priv->r->set_vlan_egr_filter(port, EGR_DISABLE); + } - priv->r->set_vlan_egr_filter(port, EGR_ENABLE); } else { /* Disable ingress and egress filtering */ if (port != priv->cpu_port) @@ -1426,6 +1432,8 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port, pr_debug("%s port %d, vid %d, flags %x\n", __func__, port, vlan->vid, vlan->flags); + if(!vlan->vid) return 0; + if (vlan->vid > 4095) { dev_err(priv->dev, "VLAN out of range: %d", vlan->vid); return -ENOTSUPP; diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h index 24d18d61fa..a642c74775 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h @@ -635,6 +635,7 @@ struct rtl838x_port { bool is2G5; int sds_num; int led_set; + int leds_on_this_port; const struct dsa_port *dp; }; diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c index c4f200bc0e..793d762489 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c @@ -24,6 +24,15 @@ #define RTL930X_LED_GLB_ACTIVE_LOW BIT(22) +#define RTL930X_LED_SETX_0_CTRL(x) (RTL930X_LED_SET0_0_CTRL - (x * 8)) +#define RTL930X_LED_SETX_1_CTRL(x) (RTL930X_LED_SETX_0_CTRL(x) - 4) + +/* get register for given set and led in the set */ +#define RTL930X_LED_SETX_LEDY(x,y) (RTL930X_LED_SETX_0_CTRL(x) - 4 * (y / 2)) + +/* get shift for given led in any set */ +#define RTL930X_LED_SET_LEDX_SHIFT(x) (16 * (x % 2)) + extern struct mutex smi_lock; extern struct rtl83xx_soc_info soc_info; @@ -249,9 +258,9 @@ static void rtl930x_vlan_fwd_on_inner(int port, bool is_set) { /* Always set all tag modes to fwd based on either inner or outer tag */ if (is_set) - sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD + (port << 2)); - else sw_w32_mask(0xf, 0, RTL930X_VLAN_PORT_FWD + (port << 2)); + else + sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD + (port << 2)); } static void rtl930x_vlan_profile_setup(int profile) @@ -2396,10 +2405,44 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) return; } + for (int set = 0; set < 4; set++) { + char set_name[16] = {0}; + u32 set_config[4]; + int leds_in_this_set = 0; + + /* Reset LED set configuration */ + sw_w32(0, RTL930X_LED_SETX_0_CTRL(set)); + sw_w32(0, RTL930X_LED_SETX_1_CTRL(set)); + + /** + * Each led set has 4 number of leds, and each LED is configured with 16 bits + * So each 32bit register holds configuration for 2 leds + * And therefore each set requires 2 registers for configuring 4 LEDs + * + */ + sprintf(set_name, "led_set%d", set); + leds_in_this_set = of_property_count_u32_elems(node, set_name); + + if (leds_in_this_set == 0 || leds_in_this_set > sizeof(set_config)) { + pr_err("%s led_set configuration invalid skipping over this set\n", __func__); + continue; + } + + if (of_property_read_u32_array(node, set_name, set_config, leds_in_this_set)) { + break; + } + + /* Write configuration as per number of LEDs */ + for (int i=0, led = leds_in_this_set-1; led >= 0; led--,i++) { + sw_w32_mask(0xffff << RTL930X_LED_SET_LEDX_SHIFT(led), + (0xffff & set_config[i]) << RTL930X_LED_SET_LEDX_SHIFT(led), + RTL930X_LED_SETX_LEDY(set, led)); + } + } + for (int i = 0; i < priv->cpu_port; i++) { int pos = (i << 1) % 32; u32 set; - u32 v; sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i)); sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_COPR_SET_SEL_CTRL(i)); @@ -2407,12 +2450,8 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) if (!priv->ports[i].phy) continue; - v = 0x1; - if (priv->ports[i].is10G) - v = 0x3; - if (priv->ports[i].phy_is_integrated) - v = 0x1; - sw_w32_mask(0x3 << pos, v << pos, RTL930X_LED_PORT_NUM_CTRL(i)); + /* 0x0 = 1 led, 0x1 = 2 leds, 0x2 = 3 leds, 0x3 = 4 leds per port */ + sw_w32_mask(0x3 << pos, (priv->ports[i].leds_on_this_port -1) << pos, RTL930X_LED_PORT_NUM_CTRL(i)); pm |= BIT(i); @@ -2421,22 +2460,6 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) sw_w32_mask(0, set << pos, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i)); } - for (int i = 0; i < 4; i++) { - const __be32 *led_set; - char set_name[9]; - u32 setlen; - u32 v; - - sprintf(set_name, "led_set%d", i); - led_set = of_get_property(node, set_name, &setlen); - if (!led_set || setlen != 16) - break; - v = be32_to_cpup(led_set) << 16 | be32_to_cpup(led_set + 1); - sw_w32(v, RTL930X_LED_SET0_0_CTRL - 4 - i * 8); - v = be32_to_cpup(led_set + 2) << 16 | be32_to_cpup(led_set + 3); - sw_w32(v, RTL930X_LED_SET0_0_CTRL - i * 8); - } - /* Set LED mode to serial (0x1) */ sw_w32_mask(0x3, 0x1, RTL930X_LED_GLB_CTRL); diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c index 3221109c18..07ac25c743 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c @@ -827,9 +827,9 @@ static void rtl931x_vlan_fwd_on_inner(int port, bool is_set) { /* Always set all tag modes to fwd based on either inner or outer tag */ if (is_set) - sw_w32_mask(0, 0xf, RTL931X_VLAN_PORT_FWD + (port << 2)); - else sw_w32_mask(0xf, 0, RTL931X_VLAN_PORT_FWD + (port << 2)); + else + sw_w32_mask(0, 0xf, RTL931X_VLAN_PORT_FWD + (port << 2)); } static void rtl931x_vlan_profile_setup(int profile) @@ -1586,9 +1586,9 @@ static void rtl931x_led_init(struct rtl838x_switch_priv *priv) sw_w32_mask(0x3 << pos, v << pos, RTL931X_LED_PORT_NUM_CTRL(i)); if (priv->ports[i].phy_is_integrated) - pm_fiber |= BIT_ULL(i); - else - pm_copper |= BIT_ULL(i); + pm_fiber |= BIT_ULL(i); + else + pm_copper |= BIT_ULL(i); set = priv->ports[i].led_set; sw_w32_mask(0, set << pos, RTL931X_LED_PORT_COPR_SET_SEL_CTRL(i)); diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c index 9dcb7a3b78..54e592aeaa 100644 --- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c @@ -43,6 +43,9 @@ extern struct rtl83xx_soc_info soc_info; #define RX_EN 0x4 #define TX_EN_93XX 0x20 #define RX_EN_93XX 0x10 +#define RX_TRUNCATE_EN_93XX BIT(6) +#define RX_TRUNCATE_EN_83XX BIT(4) +#define TX_PAD_EN_838X BIT(5) #define TX_DO 0x2 #define WRAP 0x2 #define MAX_PORTS 57 @@ -727,8 +730,8 @@ static void rtl838x_hw_en_rxtx(struct rtl838x_eth_priv *priv) /* Disable Head of Line features for all RX rings */ sw_w32(0xffffffff, priv->r->dma_if_rx_ring_size(0)); - /* Truncate RX buffer to 0x640 (1600) bytes, pad TX */ - sw_w32(0x06400020, priv->r->dma_if_ctrl); + /* Truncate RX buffer to DEFAULT_MTU bytes, pad TX */ + sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X, priv->r->dma_if_ctrl); /* Enable RX done, RX overflow and TX done interrupts */ sw_w32(0xfffff, priv->r->dma_if_intr_msk); @@ -752,7 +755,7 @@ static void rtl838x_hw_en_rxtx(struct rtl838x_eth_priv *priv) static void rtl839x_hw_en_rxtx(struct rtl838x_eth_priv *priv) { /* Setup CPU-Port: RX Buffer */ - sw_w32(0x0000c808, priv->r->dma_if_ctrl); + sw_w32((DEFAULT_MTU << 5) | RX_TRUNCATE_EN_83XX, priv->r->dma_if_ctrl); /* Enable Notify, RX done, RX overflow and TX done interrupts */ sw_w32(0x007fffff, priv->r->dma_if_intr_msk); /* Notify IRQ! */ @@ -775,8 +778,8 @@ static void rtl839x_hw_en_rxtx(struct rtl838x_eth_priv *priv) static void rtl93xx_hw_en_rxtx(struct rtl838x_eth_priv *priv) { - /* Setup CPU-Port: RX Buffer truncated at 1600 Bytes */ - sw_w32(0x06400040, priv->r->dma_if_ctrl); + /* Setup CPU-Port: RX Buffer truncated at DEFAULT_MTU Bytes */ + sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_93XX, priv->r->dma_if_ctrl); for (int i = 0; i < priv->rxrings; i++) { int pos = (i % 3) * 10; @@ -2415,7 +2418,7 @@ static int __init rtl838x_eth_probe(struct platform_device *pdev) dev->ethtool_ops = &rtl838x_ethtool_ops; dev->min_mtu = ETH_ZLEN; - dev->max_mtu = 1536; + dev->max_mtu = DEFAULT_MTU; dev->features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM; dev->hw_features = NETIF_F_RXCSUM; diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h index 7a5ff678a4..47ed286aa4 100644 --- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h @@ -216,6 +216,9 @@ /* Registers of the internal Serdes of the 8380 */ #define RTL838X_SDS4_FIB_REG0 (0xF800) +/* Default MTU with jumbo frames support */ +#define DEFAULT_MTU 9000 + inline int rtl838x_mac_port_ctrl(int p) { return RTL838X_MAC_PORT_CTRL + (p << 7); diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk index 9a9a310713..60249ff2fd 100644 --- a/target/linux/realtek/image/rtl838x.mk +++ b/target/linux/realtek/image/rtl838x.mk @@ -171,6 +171,24 @@ define Device/netgear_nge DEVICE_VENDOR := NETGEAR endef +# "NGG" refers to the uImage magic +define Device/netgear_ngg + KERNEL := \ + kernel-bin | \ + append-dtb | \ + lzma | \ + uImage lzma + KERNEL_INITRAMFS := \ + kernel-bin | \ + append-dtb | \ + lzma | \ + uImage lzma + SOC := rtl8380 + IMAGE_SIZE := 14848k + UIMAGE_MAGIC := 0x4e474720 + DEVICE_VENDOR := NETGEAR +endef + define Device/netgear_gs108t-v3 $(Device/netgear_nge) DEVICE_MODEL := GS108T @@ -186,6 +204,14 @@ define Device/netgear_gs110tpp-v1 endef TARGET_DEVICES += netgear_gs110tpp-v1 +define Device/netgear_gs110tup-v1 + $(Device/netgear_ngg) + DEVICE_MODEL := GS110TUP + DEVICE_VARIANT := v1 + DEVICE_PACKAGES += realtek-poe +endef +TARGET_DEVICES += netgear_gs110tup-v1 + define Device/netgear_gs308t-v1 $(Device/netgear_nge) DEVICE_MODEL := GS308T diff --git a/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch b/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch index 04a110a233..bf4d35764e 100644 --- a/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch +++ b/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch @@ -21,7 +21,7 @@ Submitted-by: John Crispin --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -984,6 +984,10 @@ struct phy_driver { +@@ -1009,6 +1009,10 @@ struct phy_driver { int (*led_blink_set)(struct phy_device *dev, u8 index, unsigned long *delay_on, unsigned long *delay_off); diff --git a/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch b/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch index 6b24df4674..bf6e517cfb 100644 --- a/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch +++ b/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch @@ -21,7 +21,7 @@ Submitted-by: John Crispin --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -1991,6 +1991,11 @@ int phylink_ethtool_ksettings_set(struct +@@ -1994,6 +1994,11 @@ int phylink_ethtool_ksettings_set(struct * the presence of a PHY, this should not be changed as that * should be determined from the media side advertisement. */ @@ -33,7 +33,7 @@ Submitted-by: John Crispin return phy_ethtool_ksettings_set(pl->phydev, kset); } -@@ -2294,8 +2299,11 @@ int phylink_ethtool_get_eee(struct phyli +@@ -2297,8 +2302,11 @@ int phylink_ethtool_get_eee(struct phyli ASSERT_RTNL(); @@ -46,7 +46,7 @@ Submitted-by: John Crispin return ret; } -@@ -2312,8 +2320,11 @@ int phylink_ethtool_set_eee(struct phyli +@@ -2315,8 +2323,11 @@ int phylink_ethtool_set_eee(struct phyli ASSERT_RTNL(); diff --git a/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch b/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch index 2048e22f2e..700ec97be8 100644 --- a/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch +++ b/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch @@ -13,9 +13,19 @@ Submitted-by: Birger Koblitz include/linux/phy.h | 3 +++ 2 file changed, 5 insertions(+) +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -124,6 +124,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_MOCA: + case PHY_INTERFACE_MODE_TRGMII: + case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_HSGMII: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_SMII: + case PHY_INTERFACE_MODE_1000BASEX: --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -408,6 +408,7 @@ void phylink_get_linkmodes(unsigned long +@@ -410,6 +410,7 @@ void phylink_get_linkmodes(unsigned long case PHY_INTERFACE_MODE_XGMII: case PHY_INTERFACE_MODE_RXAUI: @@ -23,7 +33,7 @@ Submitted-by: Birger Koblitz case PHY_INTERFACE_MODE_XAUI: case PHY_INTERFACE_MODE_10GBASER: case PHY_INTERFACE_MODE_10GKR: -@@ -662,6 +663,7 @@ static int phylink_parse_mode(struct phy +@@ -665,6 +666,7 @@ static int phylink_parse_mode(struct phy fallthrough; case PHY_INTERFACE_MODE_USXGMII: case PHY_INTERFACE_MODE_10GKR: @@ -33,7 +43,7 @@ Submitted-by: Birger Koblitz phylink_set(pl->supported, 10baseT_Full); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -139,6 +139,7 @@ typedef enum { +@@ -141,6 +141,7 @@ typedef enum { PHY_INTERFACE_MODE_XGMII, PHY_INTERFACE_MODE_XLGMII, PHY_INTERFACE_MODE_MOCA, @@ -41,7 +51,7 @@ Submitted-by: Birger Koblitz PHY_INTERFACE_MODE_QSGMII, PHY_INTERFACE_MODE_TRGMII, PHY_INTERFACE_MODE_100BASEX, -@@ -244,6 +245,8 @@ static inline const char *phy_modes(phy_ +@@ -248,6 +249,8 @@ static inline const char *phy_modes(phy_ return "xlgmii"; case PHY_INTERFACE_MODE_MOCA: return "moca"; diff --git a/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch b/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch index 98c5e714b1..c6f8e6508b 100644 --- a/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch +++ b/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch @@ -14,7 +14,7 @@ Submitted-by: Birger Koblitz --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -357,6 +357,12 @@ config REALTEK_PHY +@@ -354,6 +354,12 @@ config REALTEK_PHY help Supports the Realtek 821x PHY. @@ -29,7 +29,7 @@ Submitted-by: Birger Koblitz help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -93,6 +93,7 @@ obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp +@@ -89,6 +89,7 @@ obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o diff --git a/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch b/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch index 56ce80bb20..9a6b00d7c0 100644 --- a/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch +++ b/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch @@ -21,7 +21,7 @@ Submitted-by: John Crispin --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -280,7 +280,7 @@ static inline const char *phy_modes(phy_ +@@ -287,7 +287,7 @@ static inline const char *phy_modes(phy_ #define PHY_INIT_TIMEOUT 100000 #define PHY_FORCE_TIMEOUT 10 diff --git a/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch b/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch index b0a8fadb5f..188d68b121 100644 --- a/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch +++ b/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch @@ -443,7 +443,7 @@ Signed-off-by: Daniel Golle * @dev: target MDIO device --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c -@@ -482,10 +482,16 @@ int __phy_read_mmd(struct phy_device *ph +@@ -557,10 +557,16 @@ int __phy_read_mmd(struct phy_device *ph struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; @@ -464,7 +464,7 @@ Signed-off-by: Daniel Golle } return val; } -@@ -538,12 +544,18 @@ int __phy_write_mmd(struct phy_device *p +@@ -613,12 +619,18 @@ int __phy_write_mmd(struct phy_device *p struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; @@ -487,7 +487,7 @@ Signed-off-by: Daniel Golle } return ret; } -@@ -749,6 +761,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd); +@@ -824,6 +836,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd); static int __phy_read_page(struct phy_device *phydev) { @@ -501,7 +501,7 @@ Signed-off-by: Daniel Golle if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n")) return -EOPNOTSUPP; -@@ -757,6 +776,13 @@ static int __phy_read_page(struct phy_de +@@ -832,6 +851,13 @@ static int __phy_read_page(struct phy_de static int __phy_write_page(struct phy_device *phydev, int page) { @@ -515,7 +515,7 @@ Signed-off-by: Daniel Golle if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n")) return -EOPNOTSUPP; -@@ -858,6 +884,18 @@ int phy_read_paged(struct phy_device *ph +@@ -933,6 +959,18 @@ int phy_read_paged(struct phy_device *ph { int ret = 0, oldpage; @@ -534,7 +534,7 @@ Signed-off-by: Daniel Golle oldpage = phy_select_page(phydev, page); if (oldpage >= 0) ret = __phy_read(phydev, regnum); -@@ -879,6 +917,18 @@ int phy_write_paged(struct phy_device *p +@@ -954,6 +992,18 @@ int phy_write_paged(struct phy_device *p { int ret = 0, oldpage; @@ -665,7 +665,7 @@ Signed-off-by: Daniel Golle #define MDIO_DEVICE_IS_PHY 0x80000000 /** -@@ -421,6 +422,22 @@ struct mii_bus { +@@ -428,6 +429,22 @@ struct mii_bus { /** @shared: shared state across different PHYs */ struct phy_package_shared *shared[PHY_MAX_ADDR]; @@ -688,7 +688,7 @@ Signed-off-by: Daniel Golle }; #define to_mii_bus(d) container_of(d, struct mii_bus, dev) -@@ -1795,6 +1812,66 @@ static inline int __phy_package_read(str +@@ -1825,6 +1842,66 @@ static inline int __phy_package_read(str return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum); } @@ -755,7 +755,7 @@ Signed-off-by: Daniel Golle static inline int phy_package_write(struct phy_device *phydev, u32 regnum, u16 val) { -@@ -1817,6 +1894,72 @@ static inline int __phy_package_write(st +@@ -1847,6 +1924,72 @@ static inline int __phy_package_write(st return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val); } diff --git a/target/linux/rockchip/image/Makefile b/target/linux/rockchip/image/Makefile index d34948f6ae..5de053bdb6 100644 --- a/target/linux/rockchip/image/Makefile +++ b/target/linux/rockchip/image/Makefile @@ -21,7 +21,7 @@ endef define Build/boot-script # Make an U-boot image and copy it to the boot partition - mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $(if $(1),$(1),mmc).bootscript $@.boot/boot.scr + mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $(if $(1),$(1),default).bootscript $@.boot/boot.scr endef define Build/pine64-img diff --git a/target/linux/rockchip/image/mmc.bootscript b/target/linux/rockchip/image/default.bootscript similarity index 80% rename from target/linux/rockchip/image/mmc.bootscript rename to target/linux/rockchip/image/default.bootscript index 60b59e1b6b..e9de14ff7a 100644 --- a/target/linux/rockchip/image/mmc.bootscript +++ b/target/linux/rockchip/image/default.bootscript @@ -1,4 +1,4 @@ -part uuid mmc ${devnum}:2 uuid +part uuid ${devtype} ${devnum}:2 uuid if test $stdout = 'serial@fe660000' ; then serial_addr=',0xfe660000'; @@ -10,6 +10,6 @@ fi; setenv bootargs "console=ttyS2,1500000 console=tty1 earlycon=uart8250,mmio32${serial_addr} swiotlb=1 root=PARTUUID=${uuid} rw rootwait"; -load mmc ${devnum}:1 ${kernel_addr_r} kernel.img +load ${devtype} ${devnum}:1 ${kernel_addr_r} kernel.img bootm ${kernel_addr_r} diff --git a/target/linux/rockchip/patches-6.1/015-v6.8-arm64-dts-rockchip-configure-eth-pad-driver-strength-for-.patch b/target/linux/rockchip/patches-6.1/015-v6.8-arm64-dts-rockchip-configure-eth-pad-driver-strength-for-.patch new file mode 100644 index 0000000000..01efaa3a9d --- /dev/null +++ b/target/linux/rockchip/patches-6.1/015-v6.8-arm64-dts-rockchip-configure-eth-pad-driver-strength-for-.patch @@ -0,0 +1,33 @@ +From fc5a80a432607d05e85bba37971712405f75c546 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Sat, 16 Dec 2023 12:07:23 +0800 +Subject: [PATCH] arm64: dts: rockchip: configure eth pad driver strength + for orangepi r1 plus lts + +The default strength is not enough to provide stable connection +under 3.3v LDO voltage. + +Fixes: 387b3bbac5ea ("arm64: dts: rockchip: Add Xunlong OrangePi R1 Plus LTS") +Cc: stable@vger.kernel.org # 6.6+ +Signed-off-by: Tianling Shen +Link: https://lore.kernel.org/r/20231216040723.17864-1-cnsztl@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts +@@ -26,9 +26,11 @@ + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + ++ motorcomm,auto-sleep-disabled; + motorcomm,clk-out-frequency-hz = <125000000>; + motorcomm,keep-pll-enabled; +- motorcomm,auto-sleep-disabled; ++ motorcomm,rx-clk-drv-microamp = <5020>; ++ motorcomm,rx-data-drv-microamp = <5020>; + + pinctrl-0 = <ð_phy_reset_pin>; + pinctrl-names = "default"; diff --git a/toolchain/glibc/common.mk b/toolchain/glibc/common.mk index 18413cd271..6b237f5478 100644 --- a/toolchain/glibc/common.mk +++ b/toolchain/glibc/common.mk @@ -64,6 +64,7 @@ GLIBC_CONFIGURE:= \ --$(if $(CONFIG_SOFT_FLOAT),without,with)-fp \ $(if $(CONFIG_PKG_CC_STACKPROTECTOR_REGULAR),--enable-stack-protector=yes) \ $(if $(CONFIG_PKG_CC_STACKPROTECTOR_STRONG),--enable-stack-protector=strong) \ + $(if $(CONFIG_PKG_CC_STACKPROTECTOR_ALL),--enable-stack-protector=all) \ $(if $(CONFIG_PKG_RELRO_FULL),--enable-bind-now) \ --enable-kernel=5.15.0 diff --git a/tools/cpio/Makefile b/tools/cpio/Makefile index 1550785ddc..bd6e258980 100644 --- a/tools/cpio/Makefile +++ b/tools/cpio/Makefile @@ -3,11 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=cpio PKG_CPE_ID:=cpe:/a:gnu:cpio -PKG_VERSION:=2.14 +PKG_VERSION:=2.15 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=@GNU/cpio -PKG_HASH:=fcdc15d60f7267a6fc7efcd6b9db7b6c8966c4f2fbbb964c24d41336fd3f2c12 +PKG_HASH:=937610b97c329a1ec9268553fb780037bcfff0dcffe9725ebc4fd9c1aa9075db include $(INCLUDE_DIR)/host-build.mk diff --git a/tools/mkimage/Makefile b/tools/mkimage/Makefile index 5dceb9a471..ae744f9bf3 100644 --- a/tools/mkimage/Makefile +++ b/tools/mkimage/Makefile @@ -7,14 +7,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mkimage -PKG_VERSION:=2023.10 +PKG_VERSION:=2024.01 PKG_SOURCE:=u-boot-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:= \ https://mirror.cyberbits.eu/u-boot \ https://ftp.denx.de/pub/u-boot \ ftp://ftp.denx.de/pub/u-boot -PKG_HASH:=e00e6c6f014e046101739d08d06f328811cebcf5ae101348f409cbbd55ce6900 +PKG_HASH:=b99611f1ed237bf3541bdc8434b68c96a6e05967061f992443cb30aabebef5b3 HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/u-boot-$(PKG_VERSION) diff --git a/tools/mkimage/patches/030-allow-to-use-different-magic.patch b/tools/mkimage/patches/030-allow-to-use-different-magic.patch index 3689fcb531..f2f57965f6 100644 --- a/tools/mkimage/patches/030-allow-to-use-different-magic.patch +++ b/tools/mkimage/patches/030-allow-to-use-different-magic.patch @@ -50,7 +50,7 @@ This patch makes it possible to set a custom image magic. break; --- a/tools/default_image.c +++ b/tools/default_image.c -@@ -68,7 +68,7 @@ static int image_verify_header(unsigned +@@ -67,7 +67,7 @@ static int image_verify_header(unsigned */ memcpy(hdr, ptr, sizeof(struct legacy_img_hdr)); @@ -59,7 +59,7 @@ This patch makes it possible to set a custom image magic. debug("%s: Bad Magic Number: \"%s\" is no valid image\n", params->cmdname, params->imagefile); return -FDT_ERR_BADMAGIC; -@@ -147,7 +147,7 @@ static void image_set_header(void *ptr, +@@ -146,7 +146,7 @@ static void image_set_header(void *ptr, } /* Build new header */